aboutsummaryrefslogtreecommitdiff
path: root/libc/src
diff options
context:
space:
mode:
Diffstat (limited to 'libc/src')
-rw-r--r--libc/src/__support/File/linux/lseekImpl.h9
-rw-r--r--libc/src/__support/OSUtil/linux/CMakeLists.txt3
-rw-r--r--libc/src/__support/OSUtil/linux/auxv.h10
-rw-r--r--libc/src/__support/OSUtil/linux/syscall.h14
-rw-r--r--libc/src/__support/OSUtil/linux/vdso.cpp13
-rw-r--r--libc/src/__support/fixed_point/fx_bits.h111
-rw-r--r--libc/src/__support/math/CMakeLists.txt44
-rw-r--r--libc/src/__support/math/rsqrtf.h71
-rw-r--r--libc/src/__support/threads/linux/thread.cpp2
-rw-r--r--libc/src/math/CMakeLists.txt1
-rw-r--r--libc/src/math/generic/CMakeLists.txt10
-rw-r--r--libc/src/math/generic/rsqrtf.cpp16
-rw-r--r--libc/src/math/rsqrtf.h20
-rw-r--r--libc/src/stdfix/CMakeLists.txt14
-rw-r--r--libc/src/stdfix/rdivi.cpp21
-rw-r--r--libc/src/stdfix/rdivi.h21
-rw-r--r--libc/src/sys/mman/linux/mmap.cpp2
-rw-r--r--libc/src/unistd/linux/CMakeLists.txt4
-rw-r--r--libc/src/unistd/linux/sysconf.cpp11
19 files changed, 356 insertions, 41 deletions
diff --git a/libc/src/__support/File/linux/lseekImpl.h b/libc/src/__support/File/linux/lseekImpl.h
index c22a6c5..47df99a 100644
--- a/libc/src/__support/File/linux/lseekImpl.h
+++ b/libc/src/__support/File/linux/lseekImpl.h
@@ -25,8 +25,9 @@ namespace internal {
LIBC_INLINE ErrorOr<off_t> lseekimpl(int fd, off_t offset, int whence) {
off_t result;
#ifdef SYS_lseek
- int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_lseek, fd, offset, whence);
- result = ret;
+ result = LIBC_NAMESPACE::syscall_impl<off_t>(SYS_lseek, fd, offset, whence);
+ if (result < 0)
+ return Error(-static_cast<int>(result));
#elif defined(SYS_llseek) || defined(SYS__llseek)
static_assert(sizeof(size_t) == 4, "size_t must be 32 bits.");
#ifdef SYS_llseek
@@ -37,11 +38,11 @@ LIBC_INLINE ErrorOr<off_t> lseekimpl(int fd, off_t offset, int whence) {
off_t offset_64 = offset;
int ret = LIBC_NAMESPACE::syscall_impl<int>(
LLSEEK_SYSCALL_NO, fd, offset_64 >> 32, offset_64, &result, whence);
+ if (ret < 0)
+ return Error(-ret);
#else
#error "lseek, llseek and _llseek syscalls not available."
#endif
- if (ret < 0)
- return Error(-ret);
return result;
}
diff --git a/libc/src/__support/OSUtil/linux/CMakeLists.txt b/libc/src/__support/OSUtil/linux/CMakeLists.txt
index f6377ca..0a60377 100644
--- a/libc/src/__support/OSUtil/linux/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/CMakeLists.txt
@@ -70,11 +70,10 @@ add_object_library(
libc.src.__support.CPP.string_view
libc.src.__support.threads.callonce
libc.src.__support.threads.linux.futex_word_type
+ libc.src.__support.OSUtil.linux.auxv
libc.hdr.types.struct_timeval
libc.hdr.types.struct_timespec
libc.hdr.types.clockid_t
libc.hdr.types.time_t
libc.hdr.link_macros
- libc.src.errno.errno
- libc.src.sys.auxv.getauxval
)
diff --git a/libc/src/__support/OSUtil/linux/auxv.h b/libc/src/__support/OSUtil/linux/auxv.h
index 7fb996f..9c07c54 100644
--- a/libc/src/__support/OSUtil/linux/auxv.h
+++ b/libc/src/__support/OSUtil/linux/auxv.h
@@ -16,6 +16,7 @@
#include <linux/auxvec.h> // For AT_ macros
#include <linux/mman.h> // For mmap flags
+#include <linux/param.h> // For EXEC_PAGESIZE
#include <linux/prctl.h> // For prctl
#include <sys/syscall.h> // For syscall numbers
@@ -81,11 +82,16 @@ LIBC_INLINE void Vector::initialize_unsafe(const Entry *auxv) {
[[gnu::cold]]
LIBC_INLINE void Vector::fallback_initialize_unsync() {
constexpr size_t AUXV_MMAP_SIZE = FALLBACK_AUXV_ENTRIES * sizeof(Entry);
- long mmap_ret = syscall_impl<long>(SYS_mmap, nullptr, AUXV_MMAP_SIZE,
+#ifdef SYS_mmap2
+ constexpr int MMAP_SYSNO = SYS_mmap2;
+#else
+ constexpr int MMAP_SYSNO = SYS_mmap;
+#endif
+ long mmap_ret = syscall_impl<long>(MMAP_SYSNO, nullptr, AUXV_MMAP_SIZE,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
// We do not proceed if mmap fails.
- if (mmap_ret <= 0)
+ if (!linux_utils::is_valid_mmap(mmap_ret))
return;
// Initialize the auxv array with AT_NULL entries.
diff --git a/libc/src/__support/OSUtil/linux/syscall.h b/libc/src/__support/OSUtil/linux/syscall.h
index 24e0fca..0e25618 100644
--- a/libc/src/__support/OSUtil/linux/syscall.h
+++ b/libc/src/__support/OSUtil/linux/syscall.h
@@ -12,6 +12,7 @@
#include "src/__support/CPP/bit.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h"
#include "src/__support/macros/properties/architectures.h"
#ifdef LIBC_TARGET_ARCH_IS_X86_32
@@ -34,6 +35,19 @@ LIBC_INLINE R syscall_impl(long __number, Ts... ts) {
return cpp::bit_or_static_cast<R>(syscall_impl(__number, (long)ts...));
}
+// Linux-specific function for checking
+namespace linux_utils {
+LIBC_INLINE_VAR constexpr unsigned long MAX_ERRNO = 4095;
+// Ideally, this should be defined using PAGE_OFFSET
+// However, that is a configurable parameter. We mimic kernel's behavior
+// by checking against MAX_ERRNO.
+template <typename PointerLike>
+LIBC_INLINE constexpr bool is_valid_mmap(PointerLike ptr) {
+ long addr = cpp::bit_cast<long>(ptr);
+ return LIBC_LIKELY(addr > 0 || addr < -static_cast<long>(MAX_ERRNO));
+}
+} // namespace linux_utils
+
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_SYSCALL_H
diff --git a/libc/src/__support/OSUtil/linux/vdso.cpp b/libc/src/__support/OSUtil/linux/vdso.cpp
index e4e53c3..d6fd3f3 100644
--- a/libc/src/__support/OSUtil/linux/vdso.cpp
+++ b/libc/src/__support/OSUtil/linux/vdso.cpp
@@ -11,10 +11,9 @@
#include "src/__support/CPP/array.h"
#include "src/__support/CPP/optional.h"
#include "src/__support/CPP/string_view.h"
-#include "src/__support/libc_errno.h"
+#include "src/__support/OSUtil/linux/auxv.h"
#include "src/__support/threads/callonce.h"
#include "src/__support/threads/linux/futex_word.h"
-#include "src/sys/auxv/getauxval.h"
#include <linux/auxvec.h>
// TODO: This is a temporary workaround to avoid including elf.h
@@ -189,17 +188,13 @@ void Symbol::initialize_vdso_global_cache() {
for (auto &i : global_cache)
i = nullptr;
- // get the address of the VDSO, protect errno since getauxval may change
- // it
- int errno_backup = libc_errno;
- uintptr_t vdso_ehdr_addr = getauxval(AT_SYSINFO_EHDR);
+ cpp::optional<unsigned long> auxv_res = auxv::get(AT_SYSINFO_EHDR);
+ uintptr_t vdso_ehdr_addr = auxv_res ? static_cast<uintptr_t>(*auxv_res) : 0;
// Get the memory address of the vDSO ELF header.
auto vdso_ehdr = reinterpret_cast<ElfW(Ehdr) *>(vdso_ehdr_addr);
// leave the table unpopulated if we don't have vDSO
- if (vdso_ehdr == nullptr) {
- libc_errno = errno_backup;
+ if (vdso_ehdr == nullptr)
return;
- }
// locate the section header inside the elf using the section header
// offset
diff --git a/libc/src/__support/fixed_point/fx_bits.h b/libc/src/__support/fixed_point/fx_bits.h
index 00c6119b..25221d9 100644
--- a/libc/src/__support/fixed_point/fx_bits.h
+++ b/libc/src/__support/fixed_point/fx_bits.h
@@ -10,9 +10,11 @@
#define LLVM_LIBC_SRC___SUPPORT_FIXED_POINT_FX_BITS_H
#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/CPP/algorithm.h"
#include "src/__support/CPP/bit.h"
#include "src/__support/CPP/limits.h" // numeric_limits
#include "src/__support/CPP/type_traits.h"
+#include "src/__support/libc_assert.h"
#include "src/__support/macros/attributes.h" // LIBC_INLINE
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
#include "src/__support/macros/null_check.h" // LIBC_CRASH_ON_VALUE
@@ -21,6 +23,8 @@
#include "fx_rep.h"
+#include <stdio.h>
+
#ifdef LIBC_COMPILER_HAS_FIXED_POINT
namespace LIBC_NAMESPACE_DECL {
@@ -224,6 +228,113 @@ idiv(T x, T y) {
return static_cast<XType>(result);
}
+LIBC_INLINE long accum nrstep(long accum d, long accum x0) {
+ auto v = x0 * (2.lk - (d * x0));
+ return v;
+}
+
+// Divide the two integers and return a fixed_point value
+//
+// For reference, see:
+// https://en.wikipedia.org/wiki/Division_algorithm#Newton%E2%80%93Raphson_division
+// https://stackoverflow.com/a/9231996
+
+template <typename XType> LIBC_INLINE constexpr XType divi(int n, int d) {
+ // If the value of the second operand of the / operator is zero, the
+ // behavior is undefined. Ref: ISO/IEC TR 18037:2008(E) p.g. 16
+ LIBC_CRASH_ON_VALUE(d, 0);
+
+ if (LIBC_UNLIKELY(n == 0)) {
+ return FXRep<XType>::ZERO();
+ }
+ auto is_power_of_two = [](int n) { return (n > 0) && ((n & (n - 1)) == 0); };
+ long accum max_val = static_cast<long accum>(FXRep<XType>::MAX());
+ long accum min_val = static_cast<long accum>(FXRep<XType>::MIN());
+
+ if (is_power_of_two(cpp::abs(d))) {
+ int k = cpp::countr_zero<uint32_t>(static_cast<uint32_t>(cpp::abs(d)));
+ constexpr int F = FXRep<XType>::FRACTION_LEN;
+ int64_t scaled_n = static_cast<int64_t>(n) << F;
+ int64_t res64 = scaled_n >> k;
+ constexpr int TOTAL_BITS = sizeof(XType) * 8;
+ const int64_t max_limit = (1LL << (TOTAL_BITS - 1)) - 1;
+ const int64_t min_limit = -(1LL << (TOTAL_BITS - 1));
+ if (res64 > max_limit) {
+ return FXRep<XType>::MAX();
+ } else if (res64 < min_limit) {
+ return FXRep<XType>::MIN();
+ }
+ long accum res_accum =
+ static_cast<long accum>(res64) / static_cast<long accum>(1 << F);
+ res_accum = (d < 0) ? static_cast<long accum>(-1) * res_accum : res_accum;
+ if (res_accum > max_val) {
+ return FXRep<XType>::MAX();
+ } else if (res_accum < min_val) {
+ return FXRep<XType>::MIN();
+ }
+ return static_cast<XType>(res_accum);
+ }
+
+ bool result_is_negative = ((n < 0) != (d < 0));
+ int64_t n64 = static_cast<int64_t>(n);
+ int64_t d64 = static_cast<int64_t>(d);
+
+ uint64_t nv = static_cast<uint64_t>(n64 < 0 ? -n64 : n64);
+ uint64_t dv = static_cast<uint64_t>(d64 < 0 ? -d64 : d64);
+
+ if (d == INT_MIN) {
+ nv <<= 1;
+ dv >>= 1;
+ }
+
+ uint32_t clz = cpp::countl_zero<uint32_t>(static_cast<uint32_t>(dv)) - 1;
+ uint64_t scaled_val = dv << clz;
+ // Scale denominator to be in the range of [0.5,1]
+ FXBits<long accum> d_scaled{scaled_val};
+ uint64_t scaled_val_n = nv << clz;
+ // Scale the numerator as much as the denominator to maintain correctness of
+ // the original equation
+ FXBits<long accum> n_scaled{scaled_val_n};
+ long accum n_scaled_val = n_scaled.get_val();
+ long accum d_scaled_val = d_scaled.get_val();
+ // x0 = (48/17) - (32/17) * d_n
+ long accum a = 0x2.d89d89d8p0lk; // 48/17 = 2.8235294...
+ long accum b = 0x1.e1e1e1e1p0lk; // 32/17 = 1.8823529...
+ // Error of the initial approximation, as derived
+ // from the wikipedia article is
+ // E0 = 1/17 = 0.059 (5.9%)
+ long accum initial_approx = a - (b * d_scaled_val);
+ // Since, 0.5 <= d_scaled_val <= 1.0, 0.9412 <= initial_approx <= 1.88235
+ LIBC_ASSERT((initial_approx >= 0x0.78793dd9p0lk) &&
+ (initial_approx <= 0x1.f0f0d845p0lk));
+ // Each newton-raphson iteration will square the error, due
+ // to quadratic convergence. So,
+ // E1 = (0.059)^2 = 0.0034
+ long accum val = nrstep(d_scaled_val, initial_approx);
+ if constexpr (FXRep<XType>::FRACTION_LEN > 8) {
+ // E2 = 0.0000121
+ val = nrstep(d_scaled_val, val);
+ if constexpr (FXRep<XType>::FRACTION_LEN > 16) {
+ // E3 = 1.468e−10
+ val = nrstep(d_scaled_val, val);
+ }
+ }
+ long accum res = n_scaled_val * val;
+
+ if (result_is_negative) {
+ res *= static_cast<long accum>(-1);
+ }
+
+ // Per clause 7.18a.6.1, saturate values on overflow
+ if (res > max_val) {
+ return FXRep<XType>::MAX();
+ } else if (res < min_val) {
+ return FXRep<XType>::MIN();
+ } else {
+ return static_cast<XType>(res);
+ }
+}
+
} // namespace fixed_point
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 203ebb4..61253de 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -109,22 +109,6 @@ add_header_library(
libc.src.__support.macros.properties.types
)
-
-add_header_library(
- rsqrtf16
- HDRS
- rsqrtf16.h
- DEPENDS
- libc.src.__support.FPUtil.cast
- libc.src.__support.FPUtil.fenv_impl
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.multiply_add
- libc.src.__support.FPUtil.polyeval
- libc.src.__support.FPUtil.manipulation_functions
- libc.src.__support.macros.optimization
- libc.src.__support.macros.properties.types
-)
-
add_header_library(
asin_utils
HDRS
@@ -867,6 +851,34 @@ add_header_library(
)
add_header_library(
+ rsqrtf
+ HDRS
+ rsqrtf.h
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+ libc.src.__support.FPUtil.cast
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.sqrt
+ libc.src.__support.macros.optimization
+)
+
+add_header_library(
+ rsqrtf16
+ HDRS
+ rsqrtf16.h
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+ libc.src.__support.FPUtil.cast
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.sqrt
+ libc.src.__support.macros.optimization
+)
+
+add_header_library(
sincos_eval
HDRS
sincos_eval.h
diff --git a/libc/src/__support/math/rsqrtf.h b/libc/src/__support/math/rsqrtf.h
new file mode 100644
index 0000000..5da1e73
--- /dev/null
+++ b/libc/src/__support/math/rsqrtf.h
@@ -0,0 +1,71 @@
+//===-- Implementation header for rsqrtf ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_RSQRTF_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_RSQRTF_H
+
+#include "hdr/errno_macros.h"
+#include "hdr/fenv_macros.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/cast.h"
+#include "src/__support/FPUtil/sqrt.h"
+#include "src/__support/macros/optimization.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace math {
+
+LIBC_INLINE static constexpr float rsqrtf(float x) {
+ using FPBits = fputil::FPBits<float>;
+ FPBits xbits(x);
+
+ uint32_t x_u = xbits.uintval();
+ uint32_t x_abs = x_u & 0x7fff'ffffU;
+
+ constexpr uint32_t INF_BITS = FPBits::inf().uintval();
+
+ // x is 0, inf/nan, or negative.
+ if (LIBC_UNLIKELY(x_u == 0 || x_u >= INF_BITS)) {
+ // x is NaN
+ if (x_abs > INF_BITS) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+ return x;
+ }
+
+ // |x| = 0
+ if (x_abs == 0) {
+ fputil::raise_except_if_required(FE_DIVBYZERO);
+ fputil::set_errno_if_required(ERANGE);
+ return FPBits::inf(xbits.sign()).get_val();
+ }
+
+ // -inf <= x < 0
+ if (x_u > 0x7fff'ffffU) {
+ fputil::raise_except_if_required(FE_INVALID);
+ fputil::set_errno_if_required(EDOM);
+ return FPBits::quiet_nan().get_val();
+ }
+
+ // x = +inf => rsqrt(x) = 0
+ return FPBits::zero(xbits.sign()).get_val();
+ }
+
+ // TODO: add float based approximation when
+ // LIBC_TARGET_CPU_HAS_FPU_DOUBLE is not defined
+ double result = 1.0 / fputil::sqrt<double>(fputil::cast<double>(x));
+
+ return fputil::cast<float>(result);
+}
+
+} // namespace math
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_RSQRTF_H
diff --git a/libc/src/__support/threads/linux/thread.cpp b/libc/src/__support/threads/linux/thread.cpp
index d9e479ee..4f1e911 100644
--- a/libc/src/__support/threads/linux/thread.cpp
+++ b/libc/src/__support/threads/linux/thread.cpp
@@ -100,7 +100,7 @@ LIBC_INLINE ErrorOr<void *> alloc_stack(size_t stacksize, size_t guardsize) {
-1, // Not backed by any file
0 // No offset
);
- if (mmap_result < 0 && (uintptr_t(mmap_result) >= UINTPTR_MAX - size))
+ if (!linux_utils::is_valid_mmap(mmap_result))
return Error{int(-mmap_result)};
if (guardsize) {
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 3c7e99f..e37e22f 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -517,6 +517,7 @@ add_math_entrypoint_object(roundevenf16)
add_math_entrypoint_object(roundevenf128)
add_math_entrypoint_object(roundevenbf16)
+add_math_entrypoint_object(rsqrtf)
add_math_entrypoint_object(rsqrtf16)
add_math_entrypoint_object(scalbln)
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 5738fe8..55f4aaf 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -989,6 +989,16 @@ add_entrypoint_object(
)
add_entrypoint_object(
+ rsqrtf
+ SRCS
+ rsqrtf.cpp
+ HDRS
+ ../rsqrtf.h
+ DEPENDS
+ libc.src.__support.math.rsqrtf
+)
+
+add_entrypoint_object(
rsqrtf16
SRCS
rsqrtf16.cpp
diff --git a/libc/src/math/generic/rsqrtf.cpp b/libc/src/math/generic/rsqrtf.cpp
new file mode 100644
index 0000000..6a38fa7
--- /dev/null
+++ b/libc/src/math/generic/rsqrtf.cpp
@@ -0,0 +1,16 @@
+//===-- Single-precision rsqrt function -----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception.
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/math/rsqrtf.h"
+#include "src/__support/math/rsqrtf.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(float, rsqrtf, (float x)) { return math::rsqrtf(x); }
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/rsqrtf.h b/libc/src/math/rsqrtf.h
new file mode 100644
index 0000000..bc55904
--- /dev/null
+++ b/libc/src/math/rsqrtf.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for rsqrtf ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_MATH_RSQRTF_H
+#define LLVM_LIBC_SRC_MATH_RSQRTF_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+float rsqrtf(float x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_RSQRTF_H
diff --git a/libc/src/stdfix/CMakeLists.txt b/libc/src/stdfix/CMakeLists.txt
index 843111e..3cbabd1 100644
--- a/libc/src/stdfix/CMakeLists.txt
+++ b/libc/src/stdfix/CMakeLists.txt
@@ -89,6 +89,20 @@ foreach(suffix IN ITEMS r lr k lk ur ulr uk ulk)
)
endforeach()
+foreach(suffix IN ITEMS r)
+ add_entrypoint_object(
+ ${suffix}divi
+ HDRS
+ ${suffix}divi.h
+ SRCS
+ ${suffix}divi.cpp
+ COMPILE_OPTIONS
+ ${libc_opt_high_flag}
+ DEPENDS
+ libc.src.__support.fixed_point.fx_bits
+ )
+endforeach()
+
add_entrypoint_object(
uhksqrtus
HDRS
diff --git a/libc/src/stdfix/rdivi.cpp b/libc/src/stdfix/rdivi.cpp
new file mode 100644
index 0000000..7021a8b
--- /dev/null
+++ b/libc/src/stdfix/rdivi.cpp
@@ -0,0 +1,21 @@
+//===-- Implementation of rdivi function ---------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "rdivi.h"
+#include "include/llvm-libc-macros/stdfix-macros.h" // fract
+#include "src/__support/common.h" // LLVM_LIBC_FUNCTION
+#include "src/__support/fixed_point/fx_bits.h" // fixed_point
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(fract, rdivi, (int a, int b)) {
+ return fixed_point::divi<fract>(a, b);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/rdivi.h b/libc/src/stdfix/rdivi.h
new file mode 100644
index 0000000..aeda1ee
--- /dev/null
+++ b/libc/src/stdfix/rdivi.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for rdivi ------------------------*- 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_STDFIX_RDIVI_H
+#define LLVM_LIBC_SRC_STDFIX_RDIVI_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+fract rdivi(int a, int b);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_RDIVI_H
diff --git a/libc/src/sys/mman/linux/mmap.cpp b/libc/src/sys/mman/linux/mmap.cpp
index 33f9fe8..76a6611 100644
--- a/libc/src/sys/mman/linux/mmap.cpp
+++ b/libc/src/sys/mman/linux/mmap.cpp
@@ -56,7 +56,7 @@ LLVM_LIBC_FUNCTION(void *, mmap,
// However, since a valid return address cannot be within the last page, a
// return value corresponding to a location in the last page is an error
// value.
- if (ret < 0 && ret > -EXEC_PAGESIZE) {
+ if (!linux_utils::is_valid_mmap(ret)) {
libc_errno = static_cast<int>(-ret);
return MAP_FAILED;
}
diff --git a/libc/src/unistd/linux/CMakeLists.txt b/libc/src/unistd/linux/CMakeLists.txt
index dff6ba2..4eb3c7d 100644
--- a/libc/src/unistd/linux/CMakeLists.txt
+++ b/libc/src/unistd/linux/CMakeLists.txt
@@ -563,8 +563,8 @@ add_entrypoint_object(
DEPENDS
libc.include.unistd
libc.include.sys_auxv
- libc.src.errno.errno
- libc.src.sys.auxv.getauxval
+ libc.src.__support.libc_errno
+ libc.src.__support.OSUtil.linux.auxv
)
add_entrypoint_object(
diff --git a/libc/src/unistd/linux/sysconf.cpp b/libc/src/unistd/linux/sysconf.cpp
index 03f224b..979e178 100644
--- a/libc/src/unistd/linux/sysconf.cpp
+++ b/libc/src/unistd/linux/sysconf.cpp
@@ -11,17 +11,20 @@
#include "src/__support/common.h"
#include "hdr/unistd_macros.h"
+#include "src/__support/OSUtil/linux/auxv.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
-#include "src/sys/auxv/getauxval.h"
-#include <sys/auxv.h>
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(long, sysconf, (int name)) {
long ret = 0;
- if (name == _SC_PAGESIZE)
- return static_cast<long>(getauxval(AT_PAGESZ));
+ if (name == _SC_PAGESIZE) {
+ cpp::optional<unsigned long> page_size = auxv::get(AT_PAGESZ);
+ if (page_size)
+ return static_cast<long>(*page_size);
+ ret = -1;
+ }
// TODO: Complete the rest of the sysconf options.
if (ret < 0) {