diff --git a/libc/src/__support/CMakeLists.txt b/libc/src/__support/CMakeLists.txt --- a/libc/src/__support/CMakeLists.txt +++ b/libc/src/__support/CMakeLists.txt @@ -10,6 +10,8 @@ builtin_wrappers HDRS builtin_wrappers.h + DEPENDS + libc.src.__support.CPP.type_traits ) add_header_library( diff --git a/libc/src/__support/builtin_wrappers.h b/libc/src/__support/builtin_wrappers.h --- a/libc/src/__support/builtin_wrappers.h +++ b/libc/src/__support/builtin_wrappers.h @@ -10,6 +10,8 @@ #ifndef LLVM_LIBC_SRC_SUPPORT_BUILTIN_WRAPPERS_H #define LLVM_LIBC_SRC_SUPPORT_BUILTIN_WRAPPERS_H +#include "src/__support/CPP/type_traits.h" + namespace __llvm_libc { // The following overloads are matched based on what is accepted by @@ -64,6 +66,60 @@ return __internal::clz(val); } +// Add with carry +template +inline constexpr cpp::enable_if_t< + cpp::is_integral_v && cpp::is_unsigned_v, T> +add_with_carry(T a, T b, T carry_in, T &carry_out) { + T tmp = a + carry_in; + T sum = b + tmp; + carry_out = (sum < b) || (tmp < a); + return sum; +} + +#if __has_builtin(__builtin_addc) +// https://clang.llvm.org/docs/LanguageExtensions.html#multiprecision-arithmetic-builtins + +template <> +inline unsigned char add_with_carry(unsigned char a, + unsigned char b, + unsigned char carry_in, + unsigned char &carry_out) { + return __builtin_addcb(a, b, carry_in, &carry_out); +} + +template <> +inline unsigned short +add_with_carry(unsigned short a, unsigned short b, + unsigned short carry_in, + unsigned short &carry_out) { + return __builtin_addcs(a, b, carry_in, &carry_out); +} + +template <> +inline unsigned int add_with_carry(unsigned int a, unsigned int b, + unsigned int carry_in, + unsigned int &carry_out) { + return __builtin_addc(a, b, carry_in, &carry_out); +} + +template <> +inline unsigned long add_with_carry(unsigned long a, + unsigned long b, + unsigned long carry_in, + unsigned long &carry_out) { + return __builtin_addcl(a, b, carry_in, &carry_out); +} + +template <> +inline unsigned long long +add_with_carry(unsigned long long a, unsigned long long b, + unsigned long long carry_in, + unsigned long long &carry_out) { + return __builtin_addcll(a, b, carry_in, &carry_out); +} +#endif // __has_builtin(__builtin_addc) + } // namespace __llvm_libc #endif // LLVM_LIBC_SRC_SUPPORT_BUILTIN_WRAPPERS_H diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -183,6 +183,7 @@ name = "__support_builtin_wrappers", hdrs = ["src/__support/builtin_wrappers.h"], deps = [ + ":__support_cpp_type_traits", ":libc_root", ], )