diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-05-07 23:06:18 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-05-07 23:06:18 +0000 |
commit | c2bad861842aba1bb2058d583bfa74e94cfa1ffd (patch) | |
tree | 0836890776e077e1c2fb5b24d7a031bba6544f75 | |
parent | 8348f296eda4ff996db7db63fa0e79263763a99e (diff) | |
parent | 5c76e7b22aaa87ac1d8f0ae7e100327ff29eb427 (diff) | |
download | llvm-libc-sdk-release.tar.gz |
Snap for 11812660 from 5c76e7b22aaa87ac1d8f0ae7e100327ff29eb427 to sdk-releasesdk-releasebusytown-mac-infra-release
Change-Id: I3a00b36fa823ba65e8dc241910f6b555e0451511
30 files changed, 830 insertions, 14 deletions
diff --git a/include/llvm-libc-macros/linux/fcntl-macros.h b/include/llvm-libc-macros/linux/fcntl-macros.h index 1d4e5bbbdc77..8ee95863728e 100644 --- a/include/llvm-libc-macros/linux/fcntl-macros.h +++ b/include/llvm-libc-macros/linux/fcntl-macros.h @@ -67,5 +67,36 @@ #define F_SETFD 2 #define F_GETFL 3 #define F_SETFL 4 +#define F_GETLK 5 +#define F_SETLK 6 +#define F_SETLKW 7 +#define F_SETOWN 8 +#define F_GETOWN 9 +#define F_SETSIG 10 +#define F_GETSIG 11 +#define F_GETLK64 12 +#define F_SETLK64 13 +#define F_SETLKW64 14 +#define F_SETOWN_EX 15 +#define F_GETOWN_EX 16 + +// Open File Description Locks. +#define F_OFD_GETLK 36 +#define F_OFD_SETLK 37 +#define F_OFD_SETLKW 38 + +// Close on succesful +#define F_CLOEXEC 1 + +#define F_RDLCK 0 +#define F_WRLCK 1 +#define F_UNLCK 2 + +// For Large File Support +#if defined(_LARGEFILE64_SOURCE) +#define F_GETLK F_GETLK64 +#define F_SETLK F_SETLK64 +#define F_SETLKW F_SETLKW64 +#endif #endif // LLVM_LIBC_MACROS_LINUX_FCNTL_MACROS_H diff --git a/include/llvm-libc-types/char16_t.h b/include/llvm-libc-types/char16_t.h new file mode 100644 index 000000000000..1f5847ae771b --- /dev/null +++ b/include/llvm-libc-types/char16_t.h @@ -0,0 +1,17 @@ +//===-- Definition of char16_t 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_CHAR16_T_H +#define LLVM_LIBC_TYPES_CHAR16_T_H + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +#include "../llvm-libc-macros/stdint-macros.h" +typedef uint_least16_t char16_t; +#endif + +#endif // LLVM_LIBC_TYPES_CHAR16_T_H diff --git a/include/llvm-libc-types/char32_t.h b/include/llvm-libc-types/char32_t.h new file mode 100644 index 000000000000..20b72dc5d67e --- /dev/null +++ b/include/llvm-libc-types/char32_t.h @@ -0,0 +1,17 @@ +//===-- Definition of char32_t 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_CHAR32_T_H +#define LLVM_LIBC_TYPES_CHAR32_T_H + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +#include "../llvm-libc-macros/stdint-macros.h" +typedef uint_least32_t char32_t; +#endif + +#endif // LLVM_LIBC_TYPES_CHAR32_T_H diff --git a/include/llvm-libc-types/char8_t.h b/include/llvm-libc-types/char8_t.h new file mode 100644 index 000000000000..ddadab1afa21 --- /dev/null +++ b/include/llvm-libc-types/char8_t.h @@ -0,0 +1,17 @@ +//===-- Definition of char8_t 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_CHAR8_T_H +#define LLVM_LIBC_TYPES_CHAR8_T_H + +#if !defined(__cplusplus) && defined(__STDC_VERSION__) && \ + __STDC_VERSION__ >= 202311L +typedef unsigned char char8_t; +#endif + +#endif // LLVM_LIBC_TYPES_CHAR8_T_H diff --git a/include/llvm-libc-types/struct_f_owner_ex.h b/include/llvm-libc-types/struct_f_owner_ex.h new file mode 100644 index 000000000000..c9cc85f69d2b --- /dev/null +++ b/include/llvm-libc-types/struct_f_owner_ex.h @@ -0,0 +1,25 @@ +//===-- Definition of type struct f_owner_ex ------------------------------===// +// +// 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_STRUCT_F_OWNER_EX_H +#define LLVM_LIBC_TYPES_STRUCT_F_OWNER_EX_H + +#include "llvm-libc-types/pid_t.h" + +enum pid_type { + F_OWNER_TID = 0, + F_OWNER_PID, + F_OWNER_PGRP, +}; + +struct f_owner_ex { + enum pid_type type; + pid_t pid; +}; + +#endif // LLVM_LIBC_TYPES_STRUCT_F_OWNER_EX_H diff --git a/include/llvm-libc-types/struct_flock.h b/include/llvm-libc-types/struct_flock.h new file mode 100644 index 000000000000..51c9d27640ea --- /dev/null +++ b/include/llvm-libc-types/struct_flock.h @@ -0,0 +1,25 @@ +//===-- Definition of type struct flock64 ---------------------------------===// +// +// 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_STRUCT_FLOCK_H +#define LLVM_LIBC_TYPES_STRUCT_FLOCK_H + +#include "llvm-libc-types/off_t.h" +#include "llvm-libc-types/pid_t.h" + +#include <stdint.h> + +struct flock { + int16_t l_type; + int16_t l_whence; + off_t l_start; + off_t l_len; + pid_t l_pid; +}; + +#endif // LLVM_LIBC_TYPES_STRUCT_FLOCK_H diff --git a/include/llvm-libc-types/struct_flock64.h b/include/llvm-libc-types/struct_flock64.h new file mode 100644 index 000000000000..ac50003ca62f --- /dev/null +++ b/include/llvm-libc-types/struct_flock64.h @@ -0,0 +1,25 @@ +//===-- Definition of type struct flock64 ---------------------------------===// +// +// 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_STRUCT_FLOCK64_H +#define LLVM_LIBC_TYPES_STRUCT_FLOCK64_H + +#include "llvm-libc-types/off64_t.h" +#include "llvm-libc-types/pid_t.h" + +#include <stdint.h> + +struct flock64 { + int16_t l_type; + int16_t l_whence; + off64_t l_start; + off64_t l_len; + pid_t l_pid; +}; + +#endif // LLVM_LIBC_TYPES_STRUCT_FLOCK64_H diff --git a/libc/hdr/fcntl_macros.h b/libc/hdr/fcntl_macros.h new file mode 100644 index 000000000000..828cb984c0cb --- /dev/null +++ b/libc/hdr/fcntl_macros.h @@ -0,0 +1,22 @@ +//===-- Definition of macros from fcntl/fcntl.h ---------------------------===// +// +// 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_HDR_FCNTL_MACROS_H +#define LLVM_LIBC_HDR_FCNTL_MACROS_H + +#ifdef LIBC_FULL_BUILD + +#include "include/llvm-libc-macros/fcntl-macros.h" + +#else // Overlay mode + +#include <fcntl.h> + +#endif // LLVM_LIBC_FULL_BUILD + +#endif // LLVM_LIBC_HDR_FCNTL_MACROS_H diff --git a/libc/hdr/types/struct_f_owner_ex.h b/libc/hdr/types/struct_f_owner_ex.h new file mode 100644 index 000000000000..49985115ae4b --- /dev/null +++ b/libc/hdr/types/struct_f_owner_ex.h @@ -0,0 +1,21 @@ +//===-- Proxy for struct f_owner_ex --------------------------------------===// +// +// 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_HDR_TYPES_STRUCT_F_OWNER_EX_H +#define LLVM_LIBC_HDR_TYPES_STRUCT_F_OWNER_EX_H + +#ifdef LIBC_FULL_BUILD + +#include "include/llvm-libc-types/struct_f_owner_ex.h" + +#else + +#include <fcntl.h> + +#endif // LIBC_FULL_BUILD + +#endif // LLVM_LIBC_HDR_TYPES_STRUCT_F_OWNER_EX_H diff --git a/libc/hdr/types/struct_flock.h b/libc/hdr/types/struct_flock.h new file mode 100644 index 000000000000..a552b91c432b --- /dev/null +++ b/libc/hdr/types/struct_flock.h @@ -0,0 +1,21 @@ +//===-- Proxy for struct flock -------------------------------------------===// +// +// 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_HDR_TYPES_STRUCT_FLOCK_H +#define LLVM_LIBC_HDR_TYPES_STRUCT_FLOCK_H + +#ifdef LIBC_FULL_BUILD + +#include "include/llvm-libc-types/struct_flock.h" + +#else + +#include <fcntl.h> + +#endif // LIBC_FULL_BUILD + +#endif // LLVM_LIBC_HDR_TYPES_STRUCT_FLOCK_H diff --git a/libc/hdr/types/struct_flock64.h b/libc/hdr/types/struct_flock64.h new file mode 100644 index 000000000000..84fe67816c33 --- /dev/null +++ b/libc/hdr/types/struct_flock64.h @@ -0,0 +1,21 @@ +//===-- Proxy for struct flock64 -----------------------------------------===// +// +// 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_HDR_TYPES_STRUCT_FLOCK64_H +#define LLVM_LIBC_HDR_TYPES_STRUCT_FLOCK64_H + +#ifdef LIBC_FULL_BUILD + +#include "include/llvm-libc-types/struct_flock64.h" + +#else + +#include <fcntl.h> + +#endif // LIBC_FULL_BUILD + +#endif // LLVM_LIBC_HDR_TYPES_STRUCT_FLOCK64_H diff --git a/src/__support/fixed_point/sqrt.h b/src/__support/fixed_point/sqrt.h index 4ec016ceab00..982e318e2d1e 100644 --- a/src/__support/fixed_point/sqrt.h +++ b/src/__support/fixed_point/sqrt.h @@ -55,18 +55,22 @@ template <> struct SqrtConfig<unsigned fract> { // Linear approximation for the initial values, with errors bounded by: // max(1.5 * 2^-11, eps) // Generated with Sollya: - // > for i from 4 to 15 do { + // > for i from 4 to 14 do { // P = fpminimax(sqrt(x), 1, [|16, 16|], [i * 2^-4, (i + 1)*2^-4], // fixed, absolute); // print("{", coeff(P, 1), "ur,", coeff(P, 0), "ur},"); // }; + // For the last interval [15/16, 1), we choose the linear function Q such that + // Q(1) = 1 and Q(15/16) = P(15/16), + // where P is the polynomial generated by Sollya above for [14/16, 15/16]. + // This is to prevent overflow in the last interval [15/16, 1). static constexpr Type FIRST_APPROX[12][2] = { {0x1.e378p-1ur, 0x1.0ebp-2ur}, {0x1.b512p-1ur, 0x1.2b94p-2ur}, {0x1.91fp-1ur, 0x1.45dcp-2ur}, {0x1.7622p-1ur, 0x1.5e24p-2ur}, {0x1.5f5ap-1ur, 0x1.74e4p-2ur}, {0x1.4c58p-1ur, 0x1.8a4p-2ur}, {0x1.3c1ep-1ur, 0x1.9e84p-2ur}, {0x1.2e0cp-1ur, 0x1.b1d8p-2ur}, {0x1.21aap-1ur, 0x1.c468p-2ur}, {0x1.16bap-1ur, 0x1.d62cp-2ur}, - {0x1.0cfp-1ur, 0x1.e74cp-2ur}, {0x1.0418p-1ur, 0x1.f7ep-2ur}, + {0x1.0cfp-1ur, 0x1.e74cp-2ur}, {0x1.039p-1ur, 0x1.f8ep-2ur}, }; }; @@ -77,11 +81,15 @@ template <> struct SqrtConfig<unsigned long fract> { // Linear approximation for the initial values, with errors bounded by: // max(1.5 * 2^-11, eps) // Generated with Sollya: - // > for i from 4 to 15 do { + // > for i from 4 to 14 do { // P = fpminimax(sqrt(x), 1, [|32, 32|], [i * 2^-4, (i + 1)*2^-4], // fixed, absolute); // print("{", coeff(P, 1), "ulr,", coeff(P, 0), "ulr},"); // }; + // For the last interval [15/16, 1), we choose the linear function Q such that + // Q(1) = 1 and Q(15/16) = P(15/16), + // where P is the polynomial generated by Sollya above for [14/16, 15/16]. + // This is to prevent overflow in the last interval [15/16, 1). static constexpr Type FIRST_APPROX[12][2] = { {0x1.e3779b98p-1ulr, 0x1.0eaff788p-2ulr}, {0x1.b5167872p-1ulr, 0x1.2b908ad4p-2ulr}, @@ -94,7 +102,7 @@ template <> struct SqrtConfig<unsigned long fract> { {0x1.21b05c0ap-1ulr, 0x1.c45e023p-2ulr}, {0x1.16becd02p-1ulr, 0x1.d624031p-2ulr}, {0x1.0cf49fep-1ulr, 0x1.e743b844p-2ulr}, - {0x1.04214e9cp-1ulr, 0x1.f7ce2c3cp-2ulr}, + {0x1.038cdfcp-1ulr, 0x1.f8e6408p-2ulr}, }; }; diff --git a/src/fcntl/fcntl.h b/src/fcntl/fcntl.h new file mode 100644 index 000000000000..8fe3fb3146b9 --- /dev/null +++ b/src/fcntl/fcntl.h @@ -0,0 +1,18 @@ +//===-- Implementation header of fcntl --------------------------*- 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_FCNTL_FCNTL_H +#define LLVM_LIBC_SRC_FCNTL_FCNTL_H + +namespace LIBC_NAMESPACE { + +int fcntl(int fd, int cmd, ...); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_FCNTL_FCNTL_H diff --git a/src/fcntl/linux/fcntl.cpp b/src/fcntl/linux/fcntl.cpp new file mode 100644 index 000000000000..24a20fb36410 --- /dev/null +++ b/src/fcntl/linux/fcntl.cpp @@ -0,0 +1,93 @@ +//===-- Implementation of fcntl -------------------------------------------===// +// +// 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/fcntl/fcntl.h" + +#include "hdr/fcntl_macros.h" +#include "hdr/types/struct_f_owner_ex.h" +#include "hdr/types/struct_flock.h" +#include "hdr/types/struct_flock64.h" +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "src/__support/common.h" +#include "src/errno/libc_errno.h" + +#include <stdarg.h> +#include <sys/syscall.h> // For syscall numbers. + +// The OFD file locks require special handling for LARGEFILES +namespace LIBC_NAMESPACE { +LLVM_LIBC_FUNCTION(int, fcntl, (int fd, int cmd, ...)) { + void *arg; + va_list varargs; + va_start(varargs, cmd); + arg = va_arg(varargs, void *); + va_end(varargs); + + switch (cmd) { + case F_SETLKW: + return syscall_impl<int>(SYS_fcntl, fd, cmd, arg); + case F_OFD_SETLKW: { + struct flock *flk = reinterpret_cast<struct flock *>(arg); + // convert the struct to a flock64 + struct flock64 flk64; + flk64.l_type = flk->l_type; + flk64.l_whence = flk->l_whence; + flk64.l_start = flk->l_start; + flk64.l_len = flk->l_len; + flk64.l_pid = flk->l_pid; + // create a syscall + return syscall_impl<int>(SYS_fcntl, fd, cmd, &flk64); + } + case F_OFD_GETLK: + case F_OFD_SETLK: { + struct flock *flk = reinterpret_cast<struct flock *>(arg); + // convert the struct to a flock64 + struct flock64 flk64; + flk64.l_type = flk->l_type; + flk64.l_whence = flk->l_whence; + flk64.l_start = flk->l_start; + flk64.l_len = flk->l_len; + flk64.l_pid = flk->l_pid; + // create a syscall + int retVal = syscall_impl<int>(SYS_fcntl, fd, cmd, &flk64); + // On failure, return + if (retVal == -1) + return -1; + // Check for overflow, i.e. the offsets are not the same when cast + // to off_t from off64_t. + if (static_cast<off_t>(flk64.l_len) != flk64.l_len || + static_cast<off_t>(flk64.l_start) != flk64.l_start) { + libc_errno = EOVERFLOW; + return -1; + } + // Now copy back into flk, in case flk64 got modified + flk->l_type = flk64.l_type; + flk->l_whence = flk64.l_whence; + flk->l_start = flk64.l_start; + flk->l_len = flk64.l_len; + flk->l_pid = flk64.l_pid; + return retVal; + } + case F_GETOWN: { + struct f_owner_ex fex; + int retVal = syscall_impl<int>(SYS_fcntl, fd, F_GETOWN_EX, &fex); + if (retVal == -EINVAL) + return syscall_impl<int>(SYS_fcntl, fd, cmd, + reinterpret_cast<void *>(arg)); + if (static_cast<unsigned long>(retVal) <= -4096UL) + return fex.type == F_OWNER_PGRP ? -fex.pid : fex.pid; + + libc_errno = -retVal; + return -1; + } + // The general case + default: + return syscall_impl<int>(SYS_fcntl, fd, cmd, reinterpret_cast<void *>(arg)); + } +} +} // namespace LIBC_NAMESPACE diff --git a/src/math/generic/nearbyintf128.cpp b/src/math/generic/nearbyintf128.cpp new file mode 100644 index 000000000000..fca3587f5b58 --- /dev/null +++ b/src/math/generic/nearbyintf128.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of nearbyintf128 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/nearbyintf128.h" +#include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float128, nearbyintf128, (float128 x)) { + return fputil::round_using_current_rounding_mode(x); +} + +} // namespace LIBC_NAMESPACE diff --git a/src/math/generic/scalbnf128.cpp b/src/math/generic/scalbnf128.cpp new file mode 100644 index 000000000000..be3d29ed27e9 --- /dev/null +++ b/src/math/generic/scalbnf128.cpp @@ -0,0 +1,27 @@ +//===-- Implementation of scalbnf128 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/scalbnf128.h" +#include "src/__support/FPUtil/ManipulationFunctions.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float128, scalbnf128, (float128 x, int n)) { +// TODO: should be switched to use `FLT_RADIX` in hdr/float_macros.h" instead +// see: https://github.com/llvm/llvm-project/issues/90496 +#if !defined(__FLT_RADIX__) +#error __FLT_RADIX__ undefined. +#elif __FLT_RADIX__ != 2 +#error __FLT_RADIX__!=2, unimplemented. +#else + return fputil::ldexp(x, n); +#endif +} + +} // namespace LIBC_NAMESPACE diff --git a/src/math/nearbyintf128.h b/src/math/nearbyintf128.h new file mode 100644 index 000000000000..d12754a48100 --- /dev/null +++ b/src/math/nearbyintf128.h @@ -0,0 +1,20 @@ +//===-- Implementation header for nearbyintf128 -----------------*- 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_NEARBYINTF128_H +#define LLVM_LIBC_SRC_MATH_NEARBYINTF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float128 nearbyintf128(float128 x); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_NEARBYINTF128_H diff --git a/src/math/scalbnf128.h b/src/math/scalbnf128.h new file mode 100644 index 000000000000..bd3b560fb7cc --- /dev/null +++ b/src/math/scalbnf128.h @@ -0,0 +1,20 @@ +//===-- Implementation header for scalbnf128 --------------------*- 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_SCALBNF128_H +#define LLVM_LIBC_SRC_MATH_SCALBNF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float128 scalbnf128(float128 x, int n); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_SCALBNF128_H diff --git a/test/UnitTest/FPMatcher.h b/test/UnitTest/FPMatcher.h index a76e0b8ef6f6..c58c322c981e 100644 --- a/test/UnitTest/FPMatcher.h +++ b/test/UnitTest/FPMatcher.h @@ -219,4 +219,25 @@ template <typename T> struct FPTest : public Test { } \ } while (0) +#define EXPECT_FP_EQ_ROUNDING_MODE(expected, actual, rounding_mode) \ + do { \ + using namespace LIBC_NAMESPACE::fputil::testing; \ + ForceRoundingMode __r((rounding_mode)); \ + if (__r.success) { \ + EXPECT_FP_EQ((expected), (actual)); \ + } \ + } while (0) + +#define EXPECT_FP_EQ_ROUNDING_NEAREST(expected, actual) \ + EXPECT_FP_EQ_ROUNDING_MODE((expected), (actual), RoundingMode::Nearest) + +#define EXPECT_FP_EQ_ROUNDING_UPWARD(expected, actual) \ + EXPECT_FP_EQ_ROUNDING_MODE((expected), (actual), RoundingMode::Upward) + +#define EXPECT_FP_EQ_ROUNDING_DOWNWARD(expected, actual) \ + EXPECT_FP_EQ_ROUNDING_MODE((expected), (actual), RoundingMode::Downward) + +#define EXPECT_FP_EQ_ROUNDING_TOWARD_ZERO(expected, actual) \ + EXPECT_FP_EQ_ROUNDING_MODE((expected), (actual), RoundingMode::TowardZero) + #endif // LLVM_LIBC_TEST_UNITTEST_FPMATCHER_H diff --git a/test/src/fcntl/fcntl_test.cpp b/test/src/fcntl/fcntl_test.cpp new file mode 100644 index 000000000000..c5cbb61b4ed8 --- /dev/null +++ b/test/src/fcntl/fcntl_test.cpp @@ -0,0 +1,155 @@ +//===-- Unittest for fcntl ------------------------------------------------===// +// +// 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 "hdr/fcntl_macros.h" +#include "hdr/types/struct_flock.h" +#include "src/errno/libc_errno.h" +#include "src/fcntl/fcntl.h" +#include "src/fcntl/open.h" +#include "src/unistd/close.h" +#include "test/UnitTest/ErrnoSetterMatcher.h" +#include "test/UnitTest/Test.h" + +#include <stdio.h> +#include <sys/stat.h> // For S_IRWXU + +TEST(LlvmLibcFcntlTest, FcntlDupfd) { + using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; + constexpr const char *TEST_FILE_NAME = "testdata/fcntl_dup.test"; + auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME); + int fd2, fd3; + int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC, S_IRWXU); + ASSERT_ERRNO_SUCCESS(); + ASSERT_GT(fd, 0); + + fd2 = LIBC_NAMESPACE::fcntl(fd, F_DUPFD, 0); + ASSERT_ERRNO_SUCCESS(); + ASSERT_GT(fd2, 0); + + fd3 = LIBC_NAMESPACE::fcntl(fd, F_DUPFD, 10); + ASSERT_ERRNO_SUCCESS(); + ASSERT_GT(fd3, 0); + + ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0)); + ASSERT_THAT(LIBC_NAMESPACE::close(fd2), Succeeds(0)); + ASSERT_THAT(LIBC_NAMESPACE::close(fd3), Succeeds(0)); +} + +TEST(LlvmLibcFcntlTest, FcntlGetFl) { + using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; + constexpr const char *TEST_FILE_NAME = "testdata/fcntl_getfl.test"; + auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME); + int retVal; + int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC, S_IRWXU); + ASSERT_ERRNO_SUCCESS(); + ASSERT_GT(fd, 0); + + retVal = LIBC_NAMESPACE::fcntl(fd, F_GETFL); + ASSERT_ERRNO_SUCCESS(); + ASSERT_GT(retVal, -1); + + ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0)); +} + +TEST(LlvmLibcFcntlTest, FcntlSetFl) { + using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; + constexpr const char *TEST_FILE_NAME = "testdata/fcntl_setfl.test"; + auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME); + + int retVal; + int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); + ASSERT_ERRNO_SUCCESS(); + ASSERT_GT(fd, 0); + + retVal = LIBC_NAMESPACE::fcntl(fd, F_GETFL); + ASSERT_ERRNO_SUCCESS(); + ASSERT_GT(retVal, -1); + + int oldFlags = LIBC_NAMESPACE::fcntl(fd, F_GETFL, 0); + ASSERT_ERRNO_SUCCESS(); + ASSERT_GT(oldFlags, 0); + + // Add the APPEND flag; + oldFlags |= O_APPEND; + + retVal = LIBC_NAMESPACE::fcntl(fd, F_SETFL, oldFlags); + ASSERT_ERRNO_SUCCESS(); + ASSERT_GT(retVal, -1); + + // Remove the APPEND flag; + oldFlags = -oldFlags & O_APPEND; + + retVal = LIBC_NAMESPACE::fcntl(fd, F_SETFL, oldFlags); + ASSERT_ERRNO_SUCCESS(); + ASSERT_GT(retVal, -1); + + ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0)); +} + +TEST(LlvmLibcFcntlTest, FcntlGetLkRead) { + using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; + constexpr const char *TEST_FILE_NAME = "testdata/fcntl_getlkread.test"; + auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME); + + struct flock flk, svflk; + int retVal; + int fd = + LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDONLY, S_IRWXU); + ASSERT_ERRNO_SUCCESS(); + ASSERT_GT(fd, 0); + + flk.l_type = F_RDLCK; + flk.l_start = 0; + flk.l_whence = SEEK_SET; + flk.l_len = 50; + + // copy flk into svflk + svflk = flk; + + retVal = LIBC_NAMESPACE::fcntl(fd, F_GETLK, &svflk); + ASSERT_ERRNO_SUCCESS(); + ASSERT_GT(retVal, -1); + ASSERT_NE((int)flk.l_type, F_WRLCK); // File should not be write locked. + + retVal = LIBC_NAMESPACE::fcntl(fd, F_SETLK, &svflk); + ASSERT_ERRNO_SUCCESS(); + ASSERT_GT(retVal, -1); + + ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0)); +} + +TEST(LlvmLibcFcntlTest, FcntlGetLkWrite) { + using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; + constexpr const char *TEST_FILE_NAME = "testdata/fcntl_getlkwrite.test"; + auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME); + + struct flock flk, svflk; + int retVal; + int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); + ASSERT_ERRNO_SUCCESS(); + ASSERT_GT(fd, 0); + + flk.l_type = F_WRLCK; + flk.l_start = 0; + flk.l_whence = SEEK_SET; + flk.l_len = 0; + + // copy flk into svflk + svflk = flk; + + retVal = LIBC_NAMESPACE::fcntl(fd, F_GETLK, &svflk); + ASSERT_ERRNO_SUCCESS(); + ASSERT_GT(retVal, -1); + ASSERT_NE((int)flk.l_type, F_RDLCK); // File should not be read locked. + + retVal = LIBC_NAMESPACE::fcntl(fd, F_SETLK, &svflk); + ASSERT_ERRNO_SUCCESS(); + ASSERT_GT(retVal, -1); + + ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0)); +} diff --git a/test/src/math/scalbnf128_test.cpp b/test/src/math/scalbnf128_test.cpp new file mode 100644 index 000000000000..dc259de21148 --- /dev/null +++ b/test/src/math/scalbnf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for scalbnf128 ------------------------------------------===// +// +// 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 "ScalbnTest.h" + +#include "src/math/scalbnf128.h" + +LIST_SCALBN_TESTS(float128, LIBC_NAMESPACE::scalbnf128) diff --git a/test/src/math/smoke/NearbyIntTest.h b/test/src/math/smoke/NearbyIntTest.h new file mode 100644 index 000000000000..0051ff9447a7 --- /dev/null +++ b/test/src/math/smoke/NearbyIntTest.h @@ -0,0 +1,100 @@ +//===-- Utility class to test different flavors of nearbyint ----*- 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_TEST_SRC_MATH_NEARBYINTTEST_H +#define LLVM_LIBC_TEST_SRC_MATH_NEARBYINTTEST_H + +#include "hdr/fenv_macros.h" +#include "src/__support/FPUtil/FEnvImpl.h" +#include "src/__support/FPUtil/FPBits.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +static constexpr int ROUNDING_MODES[4] = {FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO, + FE_TONEAREST}; + +template <typename T> +class NearbyIntTestTemplate : public LIBC_NAMESPACE::testing::Test { + + DECLARE_SPECIAL_CONSTANTS(T) + +public: + typedef T (*NearbyIntFunc)(T); + + void testNaN(NearbyIntFunc func) { + EXPECT_FP_EQ_ALL_ROUNDING(func(aNaN), aNaN); + } + + void testInfinities(NearbyIntFunc func) { + EXPECT_FP_EQ_ALL_ROUNDING(func(inf), inf); + EXPECT_FP_EQ_ALL_ROUNDING(func(neg_inf), neg_inf); + } + + void testZeroes(NearbyIntFunc func) { + EXPECT_FP_EQ_ALL_ROUNDING(func(zero), zero); + EXPECT_FP_EQ_ALL_ROUNDING(func(neg_zero), neg_zero); + } + + void testIntegers(NearbyIntFunc func) { + EXPECT_FP_EQ_ALL_ROUNDING(func(T(1.0)), T(1.0)); + EXPECT_FP_EQ_ALL_ROUNDING(func(T(-1.0)), T(-1.0)); + + EXPECT_FP_EQ_ALL_ROUNDING(func(T(1234.0)), T(1234.0)); + EXPECT_FP_EQ_ALL_ROUNDING(func(T(-1234.0)), T(-1234.0)); + + EXPECT_FP_EQ_ALL_ROUNDING(func(T(10.0)), T(10.0)); + EXPECT_FP_EQ_ALL_ROUNDING(func(T(-10.0)), T(-10.0)); + + FPBits ints_start(T(0)); + ints_start.set_biased_exponent(FPBits::SIG_LEN + FPBits::EXP_BIAS); + T expected = ints_start.get_val(); + EXPECT_FP_EQ_ALL_ROUNDING(func(expected), expected); + } + + void testSubnormalToNearest(NearbyIntFunc func) { + ASSERT_FP_EQ(func(min_denormal), zero); + ASSERT_FP_EQ(func(-min_denormal), neg_zero); + } + + void testSubnormalTowardZero(NearbyIntFunc func) { + EXPECT_FP_EQ_ROUNDING_TOWARD_ZERO(func(min_denormal), zero); + EXPECT_FP_EQ_ROUNDING_TOWARD_ZERO(func(-min_denormal), neg_zero); + } + + void testSubnormalToPosInf(NearbyIntFunc func) { + EXPECT_FP_EQ_ROUNDING_UPWARD(func(min_denormal), FPBits::one().get_val()); + EXPECT_FP_EQ_ROUNDING_UPWARD(func(-min_denormal), neg_zero); + } + + void testSubnormalToNegInf(NearbyIntFunc func) { + T negative_one = FPBits::one(Sign::NEG).get_val(); + EXPECT_FP_EQ_ROUNDING_DOWNWARD(func(min_denormal), zero); + EXPECT_FP_EQ_ROUNDING_DOWNWARD(func(-min_denormal), negative_one); + } +}; + +#define LIST_NEARBYINT_TESTS(T, func) \ + using LlvmLibcNearbyIntTest = NearbyIntTestTemplate<T>; \ + TEST_F(LlvmLibcNearbyIntTest, TestNaN) { testNaN(&func); } \ + TEST_F(LlvmLibcNearbyIntTest, TestInfinities) { testInfinities(&func); } \ + TEST_F(LlvmLibcNearbyIntTest, TestZeroes) { testZeroes(&func); } \ + TEST_F(LlvmLibcNearbyIntTest, TestIntegers) { testIntegers(&func); } \ + TEST_F(LlvmLibcNearbyIntTest, TestSubnormalToNearest) { \ + testSubnormalToNearest(&func); \ + } \ + TEST_F(LlvmLibcNearbyIntTest, TestSubnormalTowardZero) { \ + testSubnormalTowardZero(&func); \ + } \ + TEST_F(LlvmLibcNearbyIntTest, TestSubnormalToPosInf) { \ + testSubnormalToPosInf(&func); \ + } \ + TEST_F(LlvmLibcNearbyIntTest, TestSubnormalToNegInf) { \ + testSubnormalToNegInf(&func); \ + } + +#endif // LLVM_LIBC_TEST_SRC_MATH_NEARBYINTTEST_H diff --git a/test/src/math/smoke/nearbyint_test.cpp b/test/src/math/smoke/nearbyint_test.cpp new file mode 100644 index 000000000000..11a5c3372e73 --- /dev/null +++ b/test/src/math/smoke/nearbyint_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for nearbyint -------------------------------------------===// +// +// 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 "NearbyIntTest.h" + +#include "src/math/nearbyint.h" + +LIST_NEARBYINT_TESTS(double, LIBC_NAMESPACE::nearbyint) diff --git a/test/src/math/smoke/nearbyintf128_test.cpp b/test/src/math/smoke/nearbyintf128_test.cpp new file mode 100644 index 000000000000..98fbb2858faf --- /dev/null +++ b/test/src/math/smoke/nearbyintf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for nearbyintf128 ---------------------------------------===// +// +// 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 "NearbyIntTest.h" + +#include "src/math/nearbyintf128.h" + +LIST_NEARBYINT_TESTS(float128, LIBC_NAMESPACE::nearbyintf128) diff --git a/test/src/math/smoke/nearbyintf_test.cpp b/test/src/math/smoke/nearbyintf_test.cpp new file mode 100644 index 000000000000..fd26153cfffb --- /dev/null +++ b/test/src/math/smoke/nearbyintf_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for nearbyintf ------------------------------------------===// +// +// 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 "NearbyIntTest.h" + +#include "src/math/nearbyintf.h" + +LIST_NEARBYINT_TESTS(float, LIBC_NAMESPACE::nearbyintf) diff --git a/test/src/math/smoke/nearbyintl_test.cpp b/test/src/math/smoke/nearbyintl_test.cpp new file mode 100644 index 000000000000..a6d81a1439e1 --- /dev/null +++ b/test/src/math/smoke/nearbyintl_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for nearbyintl ------------------------------------------===// +// +// 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 "NearbyIntTest.h" + +#include "src/math/nearbyintl.h" + +LIST_NEARBYINT_TESTS(long double, LIBC_NAMESPACE::nearbyintl) diff --git a/test/src/math/smoke/scalbnf128_test.cpp b/test/src/math/smoke/scalbnf128_test.cpp new file mode 100644 index 000000000000..dc259de21148 --- /dev/null +++ b/test/src/math/smoke/scalbnf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for scalbnf128 ------------------------------------------===// +// +// 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 "ScalbnTest.h" + +#include "src/math/scalbnf128.h" + +LIST_SCALBN_TESTS(float128, LIBC_NAMESPACE::scalbnf128) diff --git a/test/src/stdfix/ISqrtTest.h b/test/src/stdfix/ISqrtTest.h index 405162b706a9..ddf292fdd083 100644 --- a/test/src/stdfix/ISqrtTest.h +++ b/test/src/stdfix/ISqrtTest.h @@ -27,6 +27,18 @@ template <typename T> class ISqrtTest : public LIBC_NAMESPACE::testing::Test { public: typedef OutType (*SqrtFunc)(T); + void testSpecificInput(T input, OutType result, double expected, + double tolerance) { + double y_d = static_cast<double>(result); + double errors = LIBC_NAMESPACE::fputil::abs((y_d / expected) - 1.0); + if (errors > tolerance) { + // Print out the failure input and output. + EXPECT_EQ(input, T(0)); + EXPECT_EQ(result, zero); + } + ASSERT_TRUE(errors <= tolerance); + } + void testSpecialNumbers(SqrtFunc func) { EXPECT_EQ(zero, func(T(0))); @@ -42,15 +54,9 @@ public: for (int i = 0; i < COUNT; ++i) { x_d += 1.0; ++x; - double y_d = static_cast<double>(func(x)); - double result = LIBC_NAMESPACE::fputil::sqrt(x_d); - double errors = LIBC_NAMESPACE::fputil::abs((y_d / result) - 1.0); - if (errors > ERR) { - // Print out the failure input and output. - EXPECT_EQ(x, T(0)); - EXPECT_EQ(func(x), zero); - } - ASSERT_TRUE(errors <= ERR); + OutType result = func(x); + double expected = LIBC_NAMESPACE::fputil::sqrt(x_d); + testSpecificInput(x, result, expected, ERR); } } }; diff --git a/test/src/stdfix/SqrtTest.h b/test/src/stdfix/SqrtTest.h index 628be0deb770..47ec129fab2a 100644 --- a/test/src/stdfix/SqrtTest.h +++ b/test/src/stdfix/SqrtTest.h @@ -42,7 +42,7 @@ public: constexpr size_t COUNT = 255; constexpr StorageType STEP = - ~StorageType(0) / static_cast<StorageType>(COUNT); + StorageType(~StorageType(0)) / static_cast<StorageType>(COUNT); constexpr double ERR = 3.0 * static_cast<double>(eps); StorageType x = 0; for (size_t i = 0; i < COUNT; ++i, x += STEP) { diff --git a/test/src/stdfix/uksqrtui_test.cpp b/test/src/stdfix/uksqrtui_test.cpp index 0f4c057099da..c336d0ce1f61 100644 --- a/test/src/stdfix/uksqrtui_test.cpp +++ b/test/src/stdfix/uksqrtui_test.cpp @@ -17,4 +17,13 @@ unsigned accum uksqrtui_fast(unsigned int x) { LIST_ISQRT_TESTS(UI, unsigned int, LIBC_NAMESPACE::uksqrtui); +TEST_F(LlvmLibcISqrtUITest, LargeInteger) { + testSpecificInput(65529u, LIBC_NAMESPACE::uksqrtui(65529u), 0x1.fff8fep7, + 0x3.0p-16); +} + LIST_ISQRT_TESTS(UIFast, unsigned int, uksqrtui_fast); + +TEST_F(LlvmLibcISqrtUIFastTest, LargeInteger) { + testSpecificInput(65529u, uksqrtui_fast(65529u), 0x1.fff8fep7, 0x3.0p-16); +} |