From bec5ff793f4ec2eaafc119204450123de294fdb1 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Thu, 14 Aug 2025 13:34:33 -0400 Subject: [PATCH 1/6] [libc++] Avoid redeclaring lgamma_r This causes issues when building with modules, and redeclaring functions provided by another library (here the C library) is bad hygiene. Instead, use to access the declaration provided by the system. As a drive-by, this also starts using ::lgamma_r instead of ::lgamma when building on top of LLVM-libc. We didn't do that previously due to a declration conflict, but using the _r version when we can should only make things thread safe. --- libcxx/include/__configuration/availability.h | 13 +++++++ libcxx/include/__math/gamma.h | 25 ++++++++++++++ .../include/__random/binomial_distribution.h | 34 +++---------------- libcxx/src/CMakeLists.txt | 1 + libcxx/src/math.cpp | 26 ++++++++++++++ 5 files changed, 70 insertions(+), 29 deletions(-) create mode 100644 libcxx/src/math.cpp diff --git a/libcxx/include/__configuration/availability.h b/libcxx/include/__configuration/availability.h index 5433df872fa39..c1032b3ac26a2 100644 --- a/libcxx/include/__configuration/availability.h +++ b/libcxx/include/__configuration/availability.h @@ -84,6 +84,9 @@ // in all versions of the library are available. #if !_LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS +# define _LIBCPP_INTRODUCED_IN_LLVM_22 1 +# define _LIBCPP_INTRODUCED_IN_LLVM_22_ATTRIBUTE /* nothing */ + # define _LIBCPP_INTRODUCED_IN_LLVM_21 1 # define _LIBCPP_INTRODUCED_IN_LLVM_21_ATTRIBUTE /* nothing */ @@ -112,6 +115,11 @@ // clang-format off +// LLVM 22 +// TODO: Fill this in +# define _LIBCPP_INTRODUCED_IN_LLVM_22 0 +# define _LIBCPP_INTRODUCED_IN_LLVM_22_ATTRIBUTE __attribute__((unavailable)) + // LLVM 21 // TODO: Fill this in # define _LIBCPP_INTRODUCED_IN_LLVM_21 0 @@ -317,6 +325,11 @@ #define _LIBCPP_AVAILABILITY_HAS_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE _LIBCPP_INTRODUCED_IN_LLVM_21 // No attribute, since we've had bad_function_call::what() in the headers before +// This controls whether we provide an implementation of a thread safe variant of the `std::lgamma` +// function in the dylib. +#define _LIBCPP_AVAILABILITY_HAS_THREAD_SAFE_LGAMMA _LIBCPP_INTRODUCED_IN_LLVM_22 +// No attribute, since we call ::lgamma_r instead + // Define availability attributes that depend on both // _LIBCPP_HAS_EXCEPTIONS and _LIBCPP_HAS_RTTI. #if !_LIBCPP_HAS_EXCEPTIONS || !_LIBCPP_HAS_RTTI diff --git a/libcxx/include/__math/gamma.h b/libcxx/include/__math/gamma.h index 693e111a84e99..66fce3b5646de 100644 --- a/libcxx/include/__math/gamma.h +++ b/libcxx/include/__math/gamma.h @@ -55,6 +55,31 @@ inline _LIBCPP_HIDE_FROM_ABI double tgamma(_A1 __x) _NOEXCEPT { return __builtin_tgamma((double)__x); } +// __lgamma_r + +struct __lgamma_result { + double __result; + int __sign; +}; + +#if _LIBCPP_AVAILABILITY_HAS_THREAD_SAFE_LGAMMA +_LIBCPP_EXPORTED_FROM_ABI __lgamma_result __lgamma_thread_safe_impl(double) _NOEXCEPT; + +inline _LIBCPP_HIDE_FROM_ABI __lgamma_result __lgamma_thread_safe(double __d) _NOEXCEPT { + return __math::__lgamma_thread_safe_impl(__d); +} +#else +// When deploying to older targets, call `lgamma_r` directly but avoid declaring the actual +// function since different platforms declare the function slightly differently. +double __lgamma_r_shim(double, int*) _NOEXCEPT __asm__("lgamma_r"); + +inline _LIBCPP_HIDE_FROM_ABI __lgamma_result __lgamma_thread_safe(double __d) _NOEXCEPT { + int __sign; + double __res = __math::__lgamma_r_shim(__d, &__sign); + return __lgamma_result{__res, __sign}; +} +#endif + } // namespace __math _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__random/binomial_distribution.h b/libcxx/include/__random/binomial_distribution.h index bada8cfdd74a3..2b74c592306b9 100644 --- a/libcxx/include/__random/binomial_distribution.h +++ b/libcxx/include/__random/binomial_distribution.h @@ -10,6 +10,7 @@ #define _LIBCPP___RANDOM_BINOMIAL_DISTRIBUTION_H #include <__config> +#include <__math/gamma.h> #include <__random/is_valid.h> #include <__random/uniform_real_distribution.h> #include @@ -97,39 +98,14 @@ class binomial_distribution { } }; -// Some libc declares the math functions to be `noexcept`. -#if defined(_LIBCPP_GLIBC_PREREQ) -# if _LIBCPP_GLIBC_PREREQ(2, 8) -# define _LIBCPP_LGAMMA_R_NOEXCEPT _NOEXCEPT -# else -# define _LIBCPP_LGAMMA_R_NOEXCEPT -# endif -#elif defined(__LLVM_LIBC__) -# define _LIBCPP_LGAMMA_R_NOEXCEPT _NOEXCEPT -#else -# define _LIBCPP_LGAMMA_R_NOEXCEPT -#endif - -#if !defined(_LIBCPP_MSVCRT_LIKE) -extern "C" double lgamma_r(double, int*) _LIBCPP_LGAMMA_R_NOEXCEPT; -#endif - -inline _LIBCPP_HIDE_FROM_ABI double __libcpp_lgamma(double __d) { -#if defined(_LIBCPP_MSVCRT_LIKE) - return lgamma(__d); -#else - int __sign; - return lgamma_r(__d, &__sign); -#endif -} - template binomial_distribution<_IntType>::param_type::param_type(result_type __t, double __p) : __t_(__t), __p_(__p) { if (0 < __p_ && __p_ < 1) { __r0_ = static_cast((__t_ + 1) * __p_); - __pr_ = std::exp( - std::__libcpp_lgamma(__t_ + 1.) - std::__libcpp_lgamma(__r0_ + 1.) - std::__libcpp_lgamma(__t_ - __r0_ + 1.) + - __r0_ * std::log(__p_) + (__t_ - __r0_) * std::log(1 - __p_)); + __pr_ = + std::exp(__math::__lgamma_thread_safe(__t_ + 1.).__result - __math::__lgamma_thread_safe(__r0_ + 1.).__result - + __math::__lgamma_thread_safe(__t_ - __r0_ + 1.).__result + __r0_ * std::log(__p_) + + (__t_ - __r0_) * std::log(1 - __p_)); __odds_ratio_ = __p_ / (1 - __p_); } } diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt index f59fe0e08fccb..16e9a2e163dad 100644 --- a/libcxx/src/CMakeLists.txt +++ b/libcxx/src/CMakeLists.txt @@ -30,6 +30,7 @@ set(LIBCXX_SOURCES include/ryu/ryu.h include/to_chars_floating_point.h include/from_chars_floating_point.h + math.cpp memory.cpp memory_resource.cpp new_handler.cpp diff --git a/libcxx/src/math.cpp b/libcxx/src/math.cpp new file mode 100644 index 0000000000000..2b33f919a4d70 --- /dev/null +++ b/libcxx/src/math.cpp @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifdef __APPLE__ +# define _REENTRANT +#endif + +#include +#include // for lgamma_r + +_LIBCPP_BEGIN_NAMESPACE_STD +namespace __math { + +_LIBCPP_EXPORTED_FROM_ABI __lgamma_result __lgamma_thread_safe_impl(double __d) noexcept { + int __sign; + double __result = ::lgamma_r(__d, &__sign); + return __lgamma_result{__result, __sign}; +} + +} // namespace __math +_LIBCPP_END_NAMESPACE_STD From f580f124da9220fa1071c892bb2aa1639fdf80db Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Tue, 16 Sep 2025 16:00:22 -0400 Subject: [PATCH 2/6] Handle ABIlist --- libcxx/lib/abi/CHANGELOG.TXT | 10 ++++++++++ ...darwin.libcxxabi.v1.stable.exceptions.nonew.abilist | 1 + ...roid21.libcxxabi.v1.stable.exceptions.nonew.abilist | 1 + ...bm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist | 1 + ...bm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist | 1 + ...darwin.libcxxabi.v1.stable.exceptions.nonew.abilist | 1 + ...roid21.libcxxabi.v1.stable.exceptions.nonew.abilist | 1 + ...reebsd.libcxxabi.v1.stable.exceptions.nonew.abilist | 1 + ...ux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist | 1 + ...-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist | 1 + 10 files changed, 19 insertions(+) diff --git a/libcxx/lib/abi/CHANGELOG.TXT b/libcxx/lib/abi/CHANGELOG.TXT index 968dc7a22a8c7..f6064bf052687 100644 --- a/libcxx/lib/abi/CHANGELOG.TXT +++ b/libcxx/lib/abi/CHANGELOG.TXT @@ -16,6 +16,16 @@ New entries should be added directly below the "Version" header. Version 22.0 ------------ +* [libc++] Add a thread-safe version of std::lgamma in the dylib + + This patch adds a new function __lgamma_thread_safe in the dylib to avoid having to redeclare + ::lgamma_r within libc++'s own headers. This merely introduces a new symbol so it's not an ABI + break. + + All platforms + ------------- + Symbol added: _ZNSt3__16__math25__lgamma_thread_safe_implEd + * [libc++] Remove __time_get_storage::{__analyze,init} from the ABI These functions have never been used outside the dylib, so there is no point in exporting them. diff --git a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist index 3a1d8950c2db0..f5da8dabefe48 100644 --- a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -1692,6 +1692,7 @@ {'is_defined': True, 'name': '__ZNSt3__15wcoutE', 'size': 0, 'type': 'OBJECT'} {'is_defined': True, 'name': '__ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__16__itoa8__u64toaEyPc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist index 313de84df20e8..92dedea3e6a1b 100644 --- a/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -1329,6 +1329,7 @@ {'is_defined': True, 'name': '_ZNSt6__ndk16__clocEv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt6__ndk16__itoa8__u32toaEjPc', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt6__ndk16__itoa8__u64toaEyPc', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt6__ndk16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt6__ndk16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt6__ndk16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt6__ndk16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist index 99cde72885cf2..f1244d12570c1 100644 --- a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -677,6 +677,7 @@ {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__clocEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEyPc', 'storage_mapping_class': 'DS', 'type': 'FUNC'} +{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12steady_clock3nowEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12system_clock11from_time_tEi', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12system_clock3nowEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist index 577d6cf759a77..af16461b1cd78 100644 --- a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -677,6 +677,7 @@ {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__clocEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEmPc', 'storage_mapping_class': 'DS', 'type': 'FUNC'} +{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12steady_clock3nowEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12system_clock11from_time_tEl', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12system_clock3nowEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist index 5173a1a76b81a..5361d12bbd0c8 100644 --- a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -1691,6 +1691,7 @@ {'is_defined': True, 'name': '__ZNSt3__15wcoutE', 'size': 0, 'type': 'OBJECT'} {'is_defined': True, 'name': '__ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__16__itoa8__u64toaEyPc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist index 1be7d8a2ac20b..e8a420e4e9122 100644 --- a/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -1329,6 +1329,7 @@ {'is_defined': True, 'name': '_ZNSt6__ndk16__clocEv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt6__ndk16__itoa8__u32toaEjPc', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt6__ndk16__itoa8__u64toaEmPc', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt6__ndk16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt6__ndk16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt6__ndk16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt6__ndk16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist index 40ae625d3bd69..bd2208f403d5b 100644 --- a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -1342,6 +1342,7 @@ {'is_defined': True, 'name': '_ZNSt3__15wcoutE', 'size': 384, 'type': 'OBJECT'} {'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEmPc', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist index 90166073b135f..bd2303afa3222 100644 --- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -1341,6 +1341,7 @@ {'is_defined': True, 'name': '_ZNSt3__16__clocEv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEmPc', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist index 5855c17cf11ed..eb7566ffe951c 100644 --- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist +++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist @@ -1312,6 +1312,7 @@ {'is_defined': True, 'name': '_ZNSt3__16__clocEv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEmPc', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'} From 58a05fdd246d4781208647f7d2dd35f5beed41ba Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Wed, 17 Sep 2025 13:54:07 -0400 Subject: [PATCH 3/6] Link against -lm --- libcxx/CMakeLists.txt | 4 ++++ libcxx/cmake/config-ix.cmake | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt index 1423b6713fd35..b959f2f244be9 100644 --- a/libcxx/CMakeLists.txt +++ b/libcxx/CMakeLists.txt @@ -681,6 +681,10 @@ function(cxx_link_system_libraries target) target_link_libraries(${target} PRIVATE atomic) endif() + if (LIBCXX_HAS_MATH_LIB) + target_link_libraries(${target} PRIVATE m) + endif() + if (MINGW) target_link_libraries(${target} PRIVATE "${MINGW_LIBRARIES}") endif() diff --git a/libcxx/cmake/config-ix.cmake b/libcxx/cmake/config-ix.cmake index 270d80575adcf..80eeda05b302a 100644 --- a/libcxx/cmake/config-ix.cmake +++ b/libcxx/cmake/config-ix.cmake @@ -110,24 +110,30 @@ if(WIN32 AND NOT MINGW) set(LIBCXX_HAS_PTHREAD_LIB NO) set(LIBCXX_HAS_RT_LIB NO) set(LIBCXX_HAS_ATOMIC_LIB NO) + set(LIBCXX_HAS_MATH_LIB NO) elseif(APPLE) set(LIBCXX_HAS_PTHREAD_LIB NO) set(LIBCXX_HAS_RT_LIB NO) set(LIBCXX_HAS_ATOMIC_LIB NO) + set(LIBCXX_HAS_MATH_LIB NO) elseif(FUCHSIA) set(LIBCXX_HAS_PTHREAD_LIB NO) set(LIBCXX_HAS_RT_LIB NO) check_library_exists(atomic __atomic_fetch_add_8 "" LIBCXX_HAS_ATOMIC_LIB) + set(LIBCXX_HAS_MATH_LIB NO) elseif(ANDROID) set(LIBCXX_HAS_PTHREAD_LIB NO) set(LIBCXX_HAS_RT_LIB NO) set(LIBCXX_HAS_ATOMIC_LIB NO) + set(LIBCXX_HAS_MATH_LIB NO) elseif(PICOLIBC) set(LIBCXX_HAS_PTHREAD_LIB NO) set(LIBCXX_HAS_RT_LIB NO) set(LIBCXX_HAS_ATOMIC_LIB NO) + set(LIBCXX_HAS_MATH_LIB NO) else() check_library_exists(pthread pthread_create "" LIBCXX_HAS_PTHREAD_LIB) check_library_exists(rt clock_gettime "" LIBCXX_HAS_RT_LIB) check_library_exists(atomic __atomic_fetch_add_8 "" LIBCXX_HAS_ATOMIC_LIB) + check_library_exists(m lgamma_r "" LIBCXX_HAS_MATH_LIB) endif() From fac6c316ae853c96215893ce59becb8ade2f1523 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Mon, 17 Nov 2025 16:59:39 -0500 Subject: [PATCH 4/6] Workaround broken flag detection on GCC --- libcxx/cmake/config-ix.cmake | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libcxx/cmake/config-ix.cmake b/libcxx/cmake/config-ix.cmake index 80eeda05b302a..91f9737d5710b 100644 --- a/libcxx/cmake/config-ix.cmake +++ b/libcxx/cmake/config-ix.cmake @@ -135,5 +135,7 @@ else() check_library_exists(pthread pthread_create "" LIBCXX_HAS_PTHREAD_LIB) check_library_exists(rt clock_gettime "" LIBCXX_HAS_RT_LIB) check_library_exists(atomic __atomic_fetch_add_8 "" LIBCXX_HAS_ATOMIC_LIB) - check_library_exists(m lgamma_r "" LIBCXX_HAS_MATH_LIB) + if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(LIBCXX_HAS_MATH_LIB ON) + endif() endif() From 5f5e5434b39e79a90394065392e33b8ca01c8ebf Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Mon, 17 Nov 2025 17:03:58 -0500 Subject: [PATCH 5/6] Remove EXPORTED_FROM_ABI --- libcxx/src/math.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/src/math.cpp b/libcxx/src/math.cpp index 2b33f919a4d70..d8cbab2bcbecd 100644 --- a/libcxx/src/math.cpp +++ b/libcxx/src/math.cpp @@ -16,7 +16,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace __math { -_LIBCPP_EXPORTED_FROM_ABI __lgamma_result __lgamma_thread_safe_impl(double __d) noexcept { +__lgamma_result __lgamma_thread_safe_impl(double __d) noexcept { int __sign; double __result = ::lgamma_r(__d, &__sign); return __lgamma_result{__result, __sign}; From 72280379f482bd23d588850f81b443b07cbc79bc Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Mon, 17 Nov 2025 17:08:56 -0500 Subject: [PATCH 6/6] Move out of __math namespace --- libcxx/include/__math/gamma.h | 8 ++++---- libcxx/include/__random/binomial_distribution.h | 7 +++---- libcxx/lib/abi/CHANGELOG.TXT | 2 +- ...le-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist | 2 +- ...c-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist | 2 +- ...4-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist | 2 +- ...le-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist | 2 +- ...n-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist | 2 +- ...linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist | 2 +- ...nux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist | 2 +- libcxx/src/math.cpp | 2 -- 11 files changed, 15 insertions(+), 18 deletions(-) diff --git a/libcxx/include/__math/gamma.h b/libcxx/include/__math/gamma.h index 66fce3b5646de..4d3c4d5d54c19 100644 --- a/libcxx/include/__math/gamma.h +++ b/libcxx/include/__math/gamma.h @@ -55,6 +55,8 @@ inline _LIBCPP_HIDE_FROM_ABI double tgamma(_A1 __x) _NOEXCEPT { return __builtin_tgamma((double)__x); } +} // namespace __math + // __lgamma_r struct __lgamma_result { @@ -66,7 +68,7 @@ struct __lgamma_result { _LIBCPP_EXPORTED_FROM_ABI __lgamma_result __lgamma_thread_safe_impl(double) _NOEXCEPT; inline _LIBCPP_HIDE_FROM_ABI __lgamma_result __lgamma_thread_safe(double __d) _NOEXCEPT { - return __math::__lgamma_thread_safe_impl(__d); + return std::__lgamma_thread_safe_impl(__d); } #else // When deploying to older targets, call `lgamma_r` directly but avoid declaring the actual @@ -75,13 +77,11 @@ double __lgamma_r_shim(double, int*) _NOEXCEPT __asm__("lgamma_r"); inline _LIBCPP_HIDE_FROM_ABI __lgamma_result __lgamma_thread_safe(double __d) _NOEXCEPT { int __sign; - double __res = __math::__lgamma_r_shim(__d, &__sign); + double __res = std::__lgamma_r_shim(__d, &__sign); return __lgamma_result{__res, __sign}; } #endif -} // namespace __math - _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___MATH_GAMMA_H diff --git a/libcxx/include/__random/binomial_distribution.h b/libcxx/include/__random/binomial_distribution.h index 2b74c592306b9..f0d76be89bf5e 100644 --- a/libcxx/include/__random/binomial_distribution.h +++ b/libcxx/include/__random/binomial_distribution.h @@ -102,10 +102,9 @@ template binomial_distribution<_IntType>::param_type::param_type(result_type __t, double __p) : __t_(__t), __p_(__p) { if (0 < __p_ && __p_ < 1) { __r0_ = static_cast((__t_ + 1) * __p_); - __pr_ = - std::exp(__math::__lgamma_thread_safe(__t_ + 1.).__result - __math::__lgamma_thread_safe(__r0_ + 1.).__result - - __math::__lgamma_thread_safe(__t_ - __r0_ + 1.).__result + __r0_ * std::log(__p_) + - (__t_ - __r0_) * std::log(1 - __p_)); + __pr_ = std::exp(std::__lgamma_thread_safe(__t_ + 1.).__result - std::__lgamma_thread_safe(__r0_ + 1.).__result - + std::__lgamma_thread_safe(__t_ - __r0_ + 1.).__result + __r0_ * std::log(__p_) + + (__t_ - __r0_) * std::log(1 - __p_)); __odds_ratio_ = __p_ / (1 - __p_); } } diff --git a/libcxx/lib/abi/CHANGELOG.TXT b/libcxx/lib/abi/CHANGELOG.TXT index f6064bf052687..8910838d225ce 100644 --- a/libcxx/lib/abi/CHANGELOG.TXT +++ b/libcxx/lib/abi/CHANGELOG.TXT @@ -24,7 +24,7 @@ Version 22.0 All platforms ------------- - Symbol added: _ZNSt3__16__math25__lgamma_thread_safe_implEd + Symbol added: _ZNSt3__125__lgamma_thread_safe_implEd * [libc++] Remove __time_get_storage::{__analyze,init} from the ABI diff --git a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist index f5da8dabefe48..7659c3c60d927 100644 --- a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -1692,7 +1692,7 @@ {'is_defined': True, 'name': '__ZNSt3__15wcoutE', 'size': 0, 'type': 'OBJECT'} {'is_defined': True, 'name': '__ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__16__itoa8__u64toaEyPc', 'type': 'FUNC'} -{'is_defined': True, 'name': '__ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__125__lgamma_thread_safe_implEd', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist index f1244d12570c1..7132aab13318a 100644 --- a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -677,7 +677,7 @@ {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__clocEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEyPc', 'storage_mapping_class': 'DS', 'type': 'FUNC'} -{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'storage_mapping_class': 'DS', 'type': 'FUNC'} +{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__125__lgamma_thread_safe_implEd', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12steady_clock3nowEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12system_clock11from_time_tEi', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12system_clock3nowEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist index af16461b1cd78..c357d04e33fc5 100644 --- a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -677,7 +677,7 @@ {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__clocEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEmPc', 'storage_mapping_class': 'DS', 'type': 'FUNC'} -{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'storage_mapping_class': 'DS', 'type': 'FUNC'} +{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__125__lgamma_thread_safe_implEd', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12steady_clock3nowEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12system_clock11from_time_tEl', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12system_clock3nowEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist index 5361d12bbd0c8..8936296d7da81 100644 --- a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -1691,7 +1691,7 @@ {'is_defined': True, 'name': '__ZNSt3__15wcoutE', 'size': 0, 'type': 'OBJECT'} {'is_defined': True, 'name': '__ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__16__itoa8__u64toaEyPc', 'type': 'FUNC'} -{'is_defined': True, 'name': '__ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__125__lgamma_thread_safe_implEd', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist index bd2208f403d5b..3b99f20c111de 100644 --- a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -1342,7 +1342,7 @@ {'is_defined': True, 'name': '_ZNSt3__15wcoutE', 'size': 384, 'type': 'OBJECT'} {'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEmPc', 'type': 'FUNC'} -{'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt3__125__lgamma_thread_safe_implEd', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist index bd2303afa3222..cd538a2e5b0b9 100644 --- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -1341,7 +1341,7 @@ {'is_defined': True, 'name': '_ZNSt3__16__clocEv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEmPc', 'type': 'FUNC'} -{'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt3__125__lgamma_thread_safe_implEd', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist index eb7566ffe951c..3d8ea59c28bd5 100644 --- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist +++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist @@ -1312,7 +1312,7 @@ {'is_defined': True, 'name': '_ZNSt3__16__clocEv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEmPc', 'type': 'FUNC'} -{'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt3__125__lgamma_thread_safe_implEd', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'} diff --git a/libcxx/src/math.cpp b/libcxx/src/math.cpp index d8cbab2bcbecd..84c323e1a0b49 100644 --- a/libcxx/src/math.cpp +++ b/libcxx/src/math.cpp @@ -14,7 +14,6 @@ #include // for lgamma_r _LIBCPP_BEGIN_NAMESPACE_STD -namespace __math { __lgamma_result __lgamma_thread_safe_impl(double __d) noexcept { int __sign; @@ -22,5 +21,4 @@ __lgamma_result __lgamma_thread_safe_impl(double __d) noexcept { return __lgamma_result{__result, __sign}; } -} // namespace __math _LIBCPP_END_NAMESPACE_STD