diff --git a/libc/config/darwin/arm/entrypoints.txt b/libc/config/darwin/arm/entrypoints.txt new file mode 100644 --- /dev/null +++ b/libc/config/darwin/arm/entrypoints.txt @@ -0,0 +1,199 @@ +set(TARGET_LIBC_ENTRYPOINTS + # ctype.h entrypoints + libc.src.ctype.isalnum + libc.src.ctype.isalpha + libc.src.ctype.isascii + libc.src.ctype.isblank + libc.src.ctype.iscntrl + libc.src.ctype.isdigit + libc.src.ctype.isgraph + libc.src.ctype.islower + libc.src.ctype.isprint + libc.src.ctype.ispunct + libc.src.ctype.isspace + libc.src.ctype.isupper + libc.src.ctype.isxdigit + libc.src.ctype.toascii + libc.src.ctype.tolower + libc.src.ctype.toupper + + # errno.h entrypoints + libc.src.errno.__errno_location + + # string.h entrypoints + libc.src.string.bcmp + libc.src.string.bzero + libc.src.string.memccpy + libc.src.string.memchr + libc.src.string.memcmp + libc.src.string.memcpy + libc.src.string.memmove + libc.src.string.mempcpy + libc.src.string.memrchr + libc.src.string.memset + libc.src.string.stpcpy + libc.src.string.stpncpy + libc.src.string.strcat + libc.src.string.strchr + libc.src.string.strcmp + libc.src.string.strcpy + libc.src.string.strcspn + libc.src.string.strlen + libc.src.string.strncat + libc.src.string.strncmp + libc.src.string.strncpy + libc.src.string.strnlen + libc.src.string.strpbrk + libc.src.string.strrchr + libc.src.string.strspn + libc.src.string.strstr + libc.src.string.strtok + libc.src.string.strtok_r + + # string.h entrypoints that depend on malloc + libc.src.string.strdup + libc.src.string.strndup + + # inttypes.h entrypoints + libc.src.inttypes.imaxdiv + libc.src.inttypes.strtoimax + libc.src.inttypes.strtoumax + + # stdlib.h entrypoints + libc.src.stdlib.abs + libc.src.stdlib.atoi + libc.src.stdlib.atof + libc.src.stdlib.atol + libc.src.stdlib.atoll + libc.src.stdlib.bsearch + libc.src.stdlib.div + libc.src.stdlib.labs + libc.src.stdlib.ldiv + libc.src.stdlib.llabs + libc.src.stdlib.lldiv + libc.src.stdlib.qsort + libc.src.stdlib.strtod + libc.src.stdlib.strtof + libc.src.stdlib.strtol + libc.src.stdlib.strtold + libc.src.stdlib.strtoll + libc.src.stdlib.strtoul + libc.src.stdlib.strtoull + + # stdlib.h external entrypoints + libc.src.stdlib.malloc + libc.src.stdlib.calloc + libc.src.stdlib.realloc + libc.src.stdlib.free +) + +set(TARGET_LIBM_ENTRYPOINTS + # fenv.h entrypoints + libc.src.fenv.feclearexcept + libc.src.fenv.fedisableexcept + libc.src.fenv.feenableexcept + libc.src.fenv.fegetenv + libc.src.fenv.fegetexcept + libc.src.fenv.fegetexceptflag + libc.src.fenv.fegetround + libc.src.fenv.feholdexcept + libc.src.fenv.fesetenv + libc.src.fenv.fesetexceptflag + libc.src.fenv.fesetround + libc.src.fenv.feraiseexcept + libc.src.fenv.fetestexcept + libc.src.fenv.feupdateenv + + # math.h entrypoints + libc.src.math.copysign + libc.src.math.copysignf + libc.src.math.copysignl + libc.src.math.ceil + libc.src.math.ceilf + libc.src.math.ceill + libc.src.math.cosf + libc.src.math.expf + libc.src.math.exp2f + libc.src.math.expm1f + libc.src.math.fabs + libc.src.math.fabsf + libc.src.math.fabsl + libc.src.math.fdim + libc.src.math.fdimf + libc.src.math.fdiml + libc.src.math.floor + libc.src.math.floorf + libc.src.math.floorl + libc.src.math.fma + libc.src.math.fmaf + libc.src.math.fmax + libc.src.math.fmaxf + libc.src.math.fmaxl + libc.src.math.fmin + libc.src.math.fminf + libc.src.math.fminl + libc.src.math.frexp + libc.src.math.frexpf + libc.src.math.frexpl + libc.src.math.hypot + libc.src.math.hypotf + libc.src.math.ilogb + libc.src.math.ilogbf + libc.src.math.ilogbl + libc.src.math.llrint + libc.src.math.llrintf + libc.src.math.llrintl + libc.src.math.llround + libc.src.math.llroundf + libc.src.math.llroundl + libc.src.math.lrint + libc.src.math.lrintf + libc.src.math.lrintl + libc.src.math.lround + libc.src.math.lroundf + libc.src.math.lroundl + libc.src.math.ldexp + libc.src.math.ldexpf + libc.src.math.ldexpl + libc.src.math.log10f + libc.src.math.log1pf + libc.src.math.log2f + libc.src.math.logf + libc.src.math.logb + libc.src.math.logbf + libc.src.math.logbl + libc.src.math.modf + libc.src.math.modff + libc.src.math.modfl + libc.src.math.nearbyint + libc.src.math.nearbyintf + libc.src.math.nearbyintl + libc.src.math.nextafter + libc.src.math.nextafterf + libc.src.math.nextafterl + libc.src.math.remainderf + libc.src.math.remainder + libc.src.math.remainderl + libc.src.math.remquof + libc.src.math.remquo + libc.src.math.remquol + libc.src.math.rint + libc.src.math.rintf + libc.src.math.rintl + libc.src.math.round + libc.src.math.roundf + libc.src.math.roundl + libc.src.math.sincosf + libc.src.math.sinf + libc.src.math.sqrt + libc.src.math.sqrtf + libc.src.math.sqrtl + libc.src.math.trunc + libc.src.math.truncf + libc.src.math.truncl +) + +set(TARGET_LLVMLIBC_ENTRYPOINTS + ${TARGET_LIBC_ENTRYPOINTS} + ${TARGET_LIBM_ENTRYPOINTS} +) diff --git a/libc/config/darwin/arm/headers.txt b/libc/config/darwin/arm/headers.txt new file mode 100644 --- /dev/null +++ b/libc/config/darwin/arm/headers.txt @@ -0,0 +1,9 @@ +set(TARGET_PUBLIC_HEADERS + libc.include.ctype + libc.include.errno + libc.include.fenv + libc.include.inttypes + libc.include.math + libc.include.stdlib + libc.include.string +) diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt --- a/libc/src/__support/FPUtil/CMakeLists.txt +++ b/libc/src/__support/FPUtil/CMakeLists.txt @@ -4,7 +4,6 @@ FEnvImpl.h BasicOperations.h DivisionAndRemainderOperations.h - FEnvUtils.h FloatProperties.h FPBits.h BasicOperations.h diff --git a/libc/src/__support/FPUtil/FEnvImpl.h b/libc/src/__support/FPUtil/FEnvImpl.h --- a/libc/src/__support/FPUtil/FEnvImpl.h +++ b/libc/src/__support/FPUtil/FEnvImpl.h @@ -6,18 +6,21 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_SRC_SUPPORT_FPUTIL_DUMMY_FENVIMPL_H -#define LLVM_LIBC_SRC_SUPPORT_FPUTIL_DUMMY_FENVIMPL_H +#ifndef LLVM_LIBC_SRC_SUPPORT_FPUTIL_FENVIMPL_H +#define LLVM_LIBC_SRC_SUPPORT_FPUTIL_FENVIMPL_H #include "src/__support/architectures.h" #if defined(LLVM_LIBC_ARCH_AARCH64) +#if defined(__APPLE__) +#include "aarch64/fenv_darwin_impl.h" +#else #include "aarch64/FEnvImpl.h" +#endif #elif defined(LLVM_LIBC_ARCH_X86) #include "x86_64/FEnvImpl.h" #else #include -#include namespace __llvm_libc { namespace fputil { @@ -44,4 +47,4 @@ } // namespace __llvm_libc #endif -#endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_DUMMY_FENVIMPL_H +#endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_FENVIMPL_H diff --git a/libc/src/__support/FPUtil/FEnvUtils.h b/libc/src/__support/FPUtil/FEnvUtils.h deleted file mode 100644 --- a/libc/src/__support/FPUtil/FEnvUtils.h +++ /dev/null @@ -1,22 +0,0 @@ -//===-- Utilities for manipulating floating point environment ---*- 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_FPUTIL_FENVUTILS_H -#define LLVM_LIBC_SRC_SUPPORT_FPUTIL_FENVUTILS_H - -#include "src/__support/architectures.h" - -#if defined(LLVM_LIBC_ARCH_X86_64) -#include "x86_64/FEnvImpl.h" -#elif defined(LLVM_LIBC_ARCH_AARCH64) -#include "aarch64/FEnvImpl.h" -#else -#include "DummyFEnvImpl.h" -#endif - -#endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_FENVUTILS_H diff --git a/libc/src/__support/FPUtil/NearestIntegerOperations.h b/libc/src/__support/FPUtil/NearestIntegerOperations.h --- a/libc/src/__support/FPUtil/NearestIntegerOperations.h +++ b/libc/src/__support/FPUtil/NearestIntegerOperations.h @@ -9,15 +9,13 @@ #ifndef LLVM_LIBC_SRC_SUPPORT_FPUTIL_NEAREST_INTEGER_OPERATIONS_H #define LLVM_LIBC_SRC_SUPPORT_FPUTIL_NEAREST_INTEGER_OPERATIONS_H -#include "FEnvUtils.h" +#include "FEnvImpl.h" #include "FPBits.h" #include "src/__support/CPP/TypeTraits.h" -#include -#if math_errhandling & MATH_ERRNO #include -#endif +#include namespace __llvm_libc { namespace fputil { @@ -245,12 +243,10 @@ constexpr I INTEGER_MAX = -(INTEGER_MIN + 1); FPBits bits(x); auto set_domain_error_and_raise_invalid = []() { -#if math_errhandling & MATH_ERRNO - errno = EDOM; -#endif -#if math_errhandling & MATH_ERREXCEPT - raise_except(FE_INVALID); -#endif + if (math_errhandling & MATH_ERRNO) + errno = EDOM; + if (math_errhandling & MATH_ERREXCEPT) + raise_except(FE_INVALID); }; if (bits.is_inf_or_nan()) { diff --git a/libc/src/__support/FPUtil/aarch64/FEnvImpl.h b/libc/src/__support/FPUtil/aarch64/FEnvImpl.h --- a/libc/src/__support/FPUtil/aarch64/FEnvImpl.h +++ b/libc/src/__support/FPUtil/aarch64/FEnvImpl.h @@ -11,7 +11,7 @@ #include "src/__support/architectures.h" -#if !defined(LLVM_LIBC_ARCH_AARCH64) +#if !defined(LLVM_LIBC_ARCH_AARCH64) || defined(__APPLE__) #error "Invalid include" #endif @@ -118,7 +118,7 @@ } static inline int set_except(int excepts) { - uint32_t statusWord = FEnv::getControlWord(); + uint32_t statusWord = FEnv::getStatusWord(); uint32_t statusValue = FEnv::getStatusValueForExcept(excepts); statusWord |= (statusValue << FEnv::ExceptionStatusFlagsBitPosition); FEnv::writeStatusWord(statusWord); @@ -140,13 +140,14 @@ }; uint32_t toRaise = FEnv::getStatusValueForExcept(excepts); + int result = 0; if (toRaise & FEnv::INVALID) { divfunc(zero, zero); uint32_t statusWord = FEnv::getStatusWord(); if (!((statusWord >> FEnv::ExceptionStatusFlagsBitPosition) & FEnv::INVALID)) - return -1; + result = -1; } if (toRaise & FEnv::DIVBYZERO) { @@ -154,21 +155,21 @@ uint32_t statusWord = FEnv::getStatusWord(); if (!((statusWord >> FEnv::ExceptionStatusFlagsBitPosition) & FEnv::DIVBYZERO)) - return -1; + result = -1; } if (toRaise & FEnv::OVERFLOW) { divfunc(largeValue, smallValue); uint32_t statusWord = FEnv::getStatusWord(); if (!((statusWord >> FEnv::ExceptionStatusFlagsBitPosition) & FEnv::OVERFLOW)) - return -1; + result = -1; } if (toRaise & FEnv::UNDERFLOW) { divfunc(smallValue, largeValue); uint32_t statusWord = FEnv::getStatusWord(); if (!((statusWord >> FEnv::ExceptionStatusFlagsBitPosition) & FEnv::UNDERFLOW)) - return -1; + result = -1; } if (toRaise & FEnv::INEXACT) { float two = 2.0f; @@ -179,9 +180,9 @@ uint32_t statusWord = FEnv::getStatusWord(); if (!((statusWord >> FEnv::ExceptionStatusFlagsBitPosition) & FEnv::INEXACT)) - return -1; + result = -1; } - return 0; + return result; } static inline int get_round() { diff --git a/libc/src/__support/FPUtil/aarch64/fenv_darwin_impl.h b/libc/src/__support/FPUtil/aarch64/fenv_darwin_impl.h new file mode 100644 --- /dev/null +++ b/libc/src/__support/FPUtil/aarch64/fenv_darwin_impl.h @@ -0,0 +1,283 @@ +//===- darwin-aarch64 floating point env manipulation functions -*- 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_FPUTIL_AARCH64_FENV_DARWIN_IMPL_H +#define LLVM_LIBC_SRC_SUPPORT_FPUTIL_AARCH64_FENV_DARWIN_IMPL_H + +#include "src/__support/architectures.h" + +#if !defined(LLVM_LIBC_ARCH_AARCH64) || !defined(__APPLE__) +#error "Invalid include" +#endif + +#include +#include +#include + +#include "src/__support/FPUtil/FPBits.h" + +namespace __llvm_libc { +namespace fputil { + +struct FEnv { + struct FPState { + uint64_t StatusWord; + uint64_t ControlWord; + }; + + static_assert( + sizeof(fenv_t) == sizeof(FPState), + "Internal floating point state does not match the public fenv_t type."); + + static constexpr uint32_t TONEAREST = 0x0; + static constexpr uint32_t UPWARD = 0x1; + static constexpr uint32_t DOWNWARD = 0x2; + static constexpr uint32_t TOWARDZERO = 0x3; + + // These will be the exception flags we use for exception values normalized + // from both status word and control word. + // We add EX_ prefix to the names since macOS defines OVERFLOW and + // UNDERFLOW macros. + static constexpr uint32_t EX_INVALID = 0x1; + static constexpr uint32_t EX_DIVBYZERO = 0x2; + static constexpr uint32_t EX_OVERFLOW = 0x4; + static constexpr uint32_t EX_UNDERFLOW = 0x8; + static constexpr uint32_t EX_INEXACT = 0x10; + // __APPLE__ ARM64 has an extra flag that is raised when a denormal is flushed + // to zero. + static constexpr uint32_t EX_FLUSHTOZERO = 0x20; + + // Zero-th bit is the first bit. + static constexpr uint32_t ROUNDING_CONTROL_BIT_POSITION = 22; + + // In addition to the 5 floating point exceptions, macOS on arm64 defines + // another floating point exception: FE_FLUSHTOZERO, which is controlled by + // __fpcr_flush_to_zero bit in the FPCR register. This control bit is + // located in a different place from FE_FLUSHTOZERO status bit relative to + // the other exceptions. + static inline uint32_t exception_value_from_status(int status) { + return (status & FE_INVALID ? EX_INVALID : 0) | + (status & FE_DIVBYZERO ? EX_DIVBYZERO : 0) | + (status & FE_OVERFLOW ? EX_OVERFLOW : 0) | + (status & FE_UNDERFLOW ? EX_UNDERFLOW : 0) | + (status & FE_INEXACT ? EX_INEXACT : 0) | + (status & FE_FLUSHTOZERO ? EX_FLUSHTOZERO : 0); + } + + static inline uint32_t exception_value_from_control(int control) { + return (control & __fpcr_trap_invalid ? EX_INVALID : 0) | + (control & __fpcr_trap_divbyzero ? EX_DIVBYZERO : 0) | + (control & __fpcr_trap_overflow ? EX_OVERFLOW : 0) | + (control & __fpcr_trap_underflow ? EX_UNDERFLOW : 0) | + (control & __fpcr_trap_inexact ? EX_INEXACT : 0) | + (control & __fpcr_flush_to_zero ? EX_FLUSHTOZERO : 0); + } + + static inline int exception_value_to_status(uint32_t excepts) { + return (excepts & EX_INVALID ? FE_INVALID : 0) | + (excepts & EX_DIVBYZERO ? FE_DIVBYZERO : 0) | + (excepts & EX_OVERFLOW ? FE_OVERFLOW : 0) | + (excepts & EX_UNDERFLOW ? FE_UNDERFLOW : 0) | + (excepts & EX_INEXACT ? FE_INEXACT : 0) | + (excepts & EX_FLUSHTOZERO ? FE_FLUSHTOZERO : 0); + } + + static inline int exception_value_to_control(uint32_t excepts) { + return (excepts & EX_INVALID ? __fpcr_trap_invalid : 0) | + (excepts & EX_DIVBYZERO ? __fpcr_trap_divbyzero : 0) | + (excepts & EX_OVERFLOW ? __fpcr_trap_overflow : 0) | + (excepts & EX_UNDERFLOW ? __fpcr_trap_underflow : 0) | + (excepts & EX_INEXACT ? __fpcr_trap_inexact : 0) | + (excepts & EX_FLUSHTOZERO ? __fpcr_flush_to_zero : 0); + } + + static uint32_t get_control_word() { return __arm_rsr("fpcr"); } + + static void set_control_word(uint32_t fpcr) { __arm_wsr("fpcr", fpcr); } + + static uint32_t get_status_word() { return __arm_rsr("fpsr"); } + + static void set_status_word(uint32_t fpsr) { __arm_wsr("fpsr", fpsr); } +}; + +static inline int enable_except(int excepts) { + uint32_t new_excepts = FEnv::exception_value_from_status(excepts); + uint32_t control_word = FEnv::get_control_word(); + uint32_t old_excepts = FEnv::exception_value_from_control(control_word); + if (new_excepts != old_excepts) { + control_word |= FEnv::exception_value_to_control(new_excepts); + FEnv::set_control_word(control_word); + } + return FEnv::exception_value_to_status(old_excepts); +} + +static inline int disable_except(int excepts) { + uint32_t disabled_excepts = FEnv::exception_value_from_status(excepts); + uint32_t control_word = FEnv::get_control_word(); + uint32_t old_excepts = FEnv::exception_value_from_control(control_word); + control_word &= ~FEnv::exception_value_to_control(disabled_excepts); + FEnv::set_control_word(control_word); + return FEnv::exception_value_to_status(old_excepts); +} + +static inline int get_except() { + uint32_t control_word = FEnv::get_control_word(); + uint32_t enabled_excepts = FEnv::exception_value_from_control(control_word); + return FEnv::exception_value_to_status(enabled_excepts); +} + +static inline int clear_except(int excepts) { + uint32_t status_word = FEnv::get_status_word(); + uint32_t except_value = FEnv::exception_value_from_status(excepts); + status_word &= ~FEnv::exception_value_to_status(except_value); + FEnv::set_status_word(status_word); + return 0; +} + +static inline int test_except(int excepts) { + uint32_t statusWord = FEnv::get_status_word(); + uint32_t ex_value = FEnv::exception_value_from_status(excepts); + return statusWord & FEnv::exception_value_to_status(ex_value); +} + +static inline int set_except(int excepts) { + uint32_t status_word = FEnv::get_status_word(); + uint32_t new_exceptions = FEnv::exception_value_from_status(excepts); + status_word |= FEnv::exception_value_to_status(new_exceptions); + FEnv::set_status_word(status_word); + return 0; +} + +static inline int raise_except(int excepts) { + float zero = 0.0f; + float one = 1.0f; + float large_value = float(FPBits(FPBits::MAX_NORMAL)); + float small_value = float(FPBits(FPBits::MIN_NORMAL)); + auto divfunc = [](float a, float b) { + __asm__ __volatile__("ldr s0, %0\n\t" + "ldr s1, %1\n\t" + "fdiv s0, s0, s1\n\t" + : // No outputs + : "m"(a), "m"(b) + : "s0", "s1" /* s0 and s1 are clobbered */); + }; + + uint32_t to_raise = FEnv::exception_value_from_status(excepts); + int result = 0; + + if (to_raise & FEnv::EX_INVALID) { + divfunc(zero, zero); + uint32_t status_word = FEnv::get_status_word(); + if (!(FEnv::exception_value_from_status(status_word) & FEnv::EX_INVALID)) + result = -1; + } + + if (to_raise & FEnv::EX_DIVBYZERO) { + divfunc(one, zero); + uint32_t status_word = FEnv::get_status_word(); + if (!(FEnv::exception_value_from_status(status_word) & FEnv::EX_DIVBYZERO)) + result = -1; + } + if (to_raise & FEnv::EX_OVERFLOW) { + divfunc(large_value, small_value); + uint32_t status_word = FEnv::get_status_word(); + if (!(FEnv::exception_value_from_status(status_word) & FEnv::EX_OVERFLOW)) + result = -1; + } + if (to_raise & FEnv::EX_UNDERFLOW) { + divfunc(small_value, large_value); + uint32_t status_word = FEnv::get_status_word(); + if (!(FEnv::exception_value_from_status(status_word) & FEnv::EX_UNDERFLOW)) + result = -1; + } + if (to_raise & FEnv::EX_INEXACT) { + float two = 2.0f; + float three = 3.0f; + // 2.0 / 3.0 cannot be represented exactly in any radix 2 floating point + // format. + divfunc(two, three); + uint32_t status_word = FEnv::get_status_word(); + if (!(FEnv::exception_value_from_status(status_word) & FEnv::EX_INEXACT)) + result = -1; + } + if (to_raise & FEnv::EX_FLUSHTOZERO) { + // TODO: raise the flush to zero floating point exception. + result = -1; + } + return result; +} + +static inline int get_round() { + uint32_t rounding_mode = + (FEnv::get_control_word() >> FEnv::ROUNDING_CONTROL_BIT_POSITION) & 0x3; + switch (rounding_mode) { + case FEnv::TONEAREST: + return FE_TONEAREST; + case FEnv::DOWNWARD: + return FE_DOWNWARD; + case FEnv::UPWARD: + return FE_UPWARD; + case FEnv::TOWARDZERO: + return FE_TOWARDZERO; + default: + return -1; // Error value. + } +} + +static inline int set_round(int mode) { + uint16_t bit_value; + switch (mode) { + case FE_TONEAREST: + bit_value = FEnv::TONEAREST; + break; + case FE_DOWNWARD: + bit_value = FEnv::DOWNWARD; + break; + case FE_UPWARD: + bit_value = FEnv::UPWARD; + break; + case FE_TOWARDZERO: + bit_value = FEnv::TOWARDZERO; + break; + default: + return 1; // To indicate failure + } + + uint32_t control_word = FEnv::get_control_word(); + control_word &= ~(0x3 << FEnv::ROUNDING_CONTROL_BIT_POSITION); + control_word |= (bit_value << FEnv::ROUNDING_CONTROL_BIT_POSITION); + FEnv::set_control_word(control_word); + + return 0; +} + +static inline int get_env(fenv_t *envp) { + FEnv::FPState *state = reinterpret_cast(envp); + state->ControlWord = FEnv::get_control_word(); + state->StatusWord = FEnv::get_status_word(); + return 0; +} + +static inline int set_env(const fenv_t *envp) { + if (envp == FE_DFL_ENV) { + // Default status and control words bits are all zeros so we just + // write zeros. + FEnv::set_status_word(0); + FEnv::set_control_word(0); + return 0; + } + const FEnv::FPState *state = reinterpret_cast(envp); + FEnv::set_control_word(state->ControlWord); + FEnv::set_status_word(state->StatusWord); + return 0; +} + +} // namespace fputil +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_AARCH64_FENV_DARWIN_IMPL_H diff --git a/libc/src/__support/common.h b/libc/src/__support/common.h --- a/libc/src/__support/common.h +++ b/libc/src/__support/common.h @@ -19,7 +19,7 @@ #define LLVM_LIBC_FUNCTION_ATTR #endif -#ifdef LLVM_LIBC_PUBLIC_PACKAGING +#if defined(LLVM_LIBC_PUBLIC_PACKAGING) && (!defined(__APPLE__)) #define LLVM_LIBC_FUNCTION(type, name, arglist) \ LLVM_LIBC_FUNCTION_ATTR decltype(__llvm_libc::name) \ __##name##_impl__ __asm__(#name); \ diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h --- a/libc/src/__support/str_to_float.h +++ b/libc/src/__support/str_to_float.h @@ -460,8 +460,9 @@ #if defined(LONG_DOUBLE_IS_DOUBLE) template <> class ClingerConsts { public: - static constexpr long double POWERS_OF_TEN_ARRAY[] = - ClingerConsts::POWERS_OF_TEN_ARRAY; + static constexpr long double POWERS_OF_TEN_ARRAY[] = { + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, + 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22}; static constexpr int32_t EXACT_POWERS_OF_TEN = ClingerConsts::EXACT_POWERS_OF_TEN; static constexpr int32_t DIGITS_IN_MANTISSA = diff --git a/libc/src/fenv/feclearexcept.cpp b/libc/src/fenv/feclearexcept.cpp --- a/libc/src/fenv/feclearexcept.cpp +++ b/libc/src/fenv/feclearexcept.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "src/fenv/feclearexcept.h" -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/common.h" namespace __llvm_libc { diff --git a/libc/src/fenv/fedisableexcept.cpp b/libc/src/fenv/fedisableexcept.cpp --- a/libc/src/fenv/fedisableexcept.cpp +++ b/libc/src/fenv/fedisableexcept.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "src/fenv/fedisableexcept.h" -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/common.h" namespace __llvm_libc { diff --git a/libc/src/fenv/feenableexcept.cpp b/libc/src/fenv/feenableexcept.cpp --- a/libc/src/fenv/feenableexcept.cpp +++ b/libc/src/fenv/feenableexcept.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "src/fenv/feenableexcept.h" -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/common.h" namespace __llvm_libc { diff --git a/libc/src/fenv/fegetenv.cpp b/libc/src/fenv/fegetenv.cpp --- a/libc/src/fenv/fegetenv.cpp +++ b/libc/src/fenv/fegetenv.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "src/fenv/fegetenv.h" -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/common.h" namespace __llvm_libc { diff --git a/libc/src/fenv/fegetexcept.cpp b/libc/src/fenv/fegetexcept.cpp --- a/libc/src/fenv/fegetexcept.cpp +++ b/libc/src/fenv/fegetexcept.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "src/fenv/fegetexcept.h" -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/common.h" namespace __llvm_libc { diff --git a/libc/src/fenv/fegetexceptflag.cpp b/libc/src/fenv/fegetexceptflag.cpp --- a/libc/src/fenv/fegetexceptflag.cpp +++ b/libc/src/fenv/fegetexceptflag.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "src/fenv/fegetexceptflag.h" -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/common.h" #include diff --git a/libc/src/fenv/fegetround.cpp b/libc/src/fenv/fegetround.cpp --- a/libc/src/fenv/fegetround.cpp +++ b/libc/src/fenv/fegetround.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "src/fenv/fegetround.h" -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/common.h" namespace __llvm_libc { diff --git a/libc/src/fenv/feholdexcept.cpp b/libc/src/fenv/feholdexcept.cpp --- a/libc/src/fenv/feholdexcept.cpp +++ b/libc/src/fenv/feholdexcept.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "src/fenv/feholdexcept.h" -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/common.h" #include diff --git a/libc/src/fenv/feraiseexcept.cpp b/libc/src/fenv/feraiseexcept.cpp --- a/libc/src/fenv/feraiseexcept.cpp +++ b/libc/src/fenv/feraiseexcept.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "src/fenv/feraiseexcept.h" -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/common.h" namespace __llvm_libc { diff --git a/libc/src/fenv/fesetenv.cpp b/libc/src/fenv/fesetenv.cpp --- a/libc/src/fenv/fesetenv.cpp +++ b/libc/src/fenv/fesetenv.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "src/fenv/fesetenv.h" -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/common.h" namespace __llvm_libc { diff --git a/libc/src/fenv/fesetexceptflag.cpp b/libc/src/fenv/fesetexceptflag.cpp --- a/libc/src/fenv/fesetexceptflag.cpp +++ b/libc/src/fenv/fesetexceptflag.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "src/fenv/fesetexceptflag.h" -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/common.h" #include diff --git a/libc/src/fenv/fesetround.cpp b/libc/src/fenv/fesetround.cpp --- a/libc/src/fenv/fesetround.cpp +++ b/libc/src/fenv/fesetround.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "src/fenv/fesetround.h" -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/common.h" namespace __llvm_libc { diff --git a/libc/src/fenv/fetestexcept.cpp b/libc/src/fenv/fetestexcept.cpp --- a/libc/src/fenv/fetestexcept.cpp +++ b/libc/src/fenv/fetestexcept.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "src/fenv/fetestexcept.h" -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/common.h" namespace __llvm_libc { diff --git a/libc/src/fenv/feupdateenv.cpp b/libc/src/fenv/feupdateenv.cpp --- a/libc/src/fenv/feupdateenv.cpp +++ b/libc/src/fenv/feupdateenv.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "src/fenv/feupdateenv.h" -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/common.h" #include diff --git a/libc/src/math/generic/log10f.cpp b/libc/src/math/generic/log10f.cpp --- a/libc/src/math/generic/log10f.cpp +++ b/libc/src/math/generic/log10f.cpp @@ -9,7 +9,7 @@ #include "src/math/log10f.h" #include "common_constants.h" // Lookup table for (1/f) #include "src/__support/FPUtil/BasicOperations.h" -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FMA.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/PolyEval.h" diff --git a/libc/src/math/generic/log1pf.cpp b/libc/src/math/generic/log1pf.cpp --- a/libc/src/math/generic/log1pf.cpp +++ b/libc/src/math/generic/log1pf.cpp @@ -9,7 +9,7 @@ #include "src/math/log1pf.h" #include "common_constants.h" // Lookup table for (1/f) and log(f) #include "src/__support/FPUtil/BasicOperations.h" -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FMA.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/PolyEval.h" diff --git a/libc/src/math/generic/log2f.cpp b/libc/src/math/generic/log2f.cpp --- a/libc/src/math/generic/log2f.cpp +++ b/libc/src/math/generic/log2f.cpp @@ -9,7 +9,7 @@ #include "src/math/log2f.h" #include "common_constants.h" // Lookup table for (1/f) #include "src/__support/FPUtil/BasicOperations.h" -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FMA.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/PolyEval.h" diff --git a/libc/test/src/fenv/CMakeLists.txt b/libc/test/src/fenv/CMakeLists.txt --- a/libc/test/src/fenv/CMakeLists.txt +++ b/libc/test/src/fenv/CMakeLists.txt @@ -85,11 +85,13 @@ libc.src.fenv.fegetexcept ) -if (NOT (LLVM_USE_SANITIZER OR (${LIBC_TARGET_OS} STREQUAL "windows"))) +if (NOT (LLVM_USE_SANITIZER OR (${LIBC_TARGET_OS} STREQUAL "windows") + OR (${LIBC_TARGET_OS} STREQUAL "darwin"))) # Sanitizers don't like SIGFPE. So, we will run the # tests which raise SIGFPE only in non-sanitizer builds. - # The tests are also disabled for Windows as they fail currently. - # TODO: Investigate and fix the windows failures and enable them for Windows. + # The tests are also disabled for Windows and MacOS as they fail currently. + # TODO: Investigate and fix the windows failures and enable them for Windows + # and MacOS. add_fp_unittest( enabled_exceptions_test SUITE diff --git a/libc/test/src/fenv/enabled_exceptions_test.cpp b/libc/test/src/fenv/enabled_exceptions_test.cpp --- a/libc/test/src/fenv/enabled_exceptions_test.cpp +++ b/libc/test/src/fenv/enabled_exceptions_test.cpp @@ -10,7 +10,7 @@ #include "src/fenv/feraiseexcept.h" #include "src/fenv/fetestexcept.h" -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/architectures.h" #include "utils/UnitTest/FPExceptMatcher.h" #include "utils/UnitTest/Test.h" diff --git a/libc/test/src/fenv/exception_flags_test.cpp b/libc/test/src/fenv/exception_flags_test.cpp --- a/libc/test/src/fenv/exception_flags_test.cpp +++ b/libc/test/src/fenv/exception_flags_test.cpp @@ -9,7 +9,7 @@ #include "src/fenv/fegetexceptflag.h" #include "src/fenv/fesetexceptflag.h" -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "utils/UnitTest/Test.h" #include diff --git a/libc/test/src/fenv/exception_status_test.cpp b/libc/test/src/fenv/exception_status_test.cpp --- a/libc/test/src/fenv/exception_status_test.cpp +++ b/libc/test/src/fenv/exception_status_test.cpp @@ -10,7 +10,7 @@ #include "src/fenv/feraiseexcept.h" #include "src/fenv/fetestexcept.h" -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "utils/UnitTest/Test.h" #include diff --git a/libc/test/src/fenv/feclearexcept_test.cpp b/libc/test/src/fenv/feclearexcept_test.cpp --- a/libc/test/src/fenv/feclearexcept_test.cpp +++ b/libc/test/src/fenv/feclearexcept_test.cpp @@ -8,7 +8,7 @@ #include "src/fenv/feclearexcept.h" -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "utils/UnitTest/Test.h" #include @@ -24,56 +24,14 @@ ASSERT_EQ(__llvm_libc::fputil::test_except(e), 0); __llvm_libc::fputil::raise_except(FE_ALL_EXCEPT); - for (uint16_t e : excepts) { - // We clear one exception and test to verify that it was cleared. - __llvm_libc::feclearexcept(e); - ASSERT_EQ(uint16_t(__llvm_libc::fputil::test_except(FE_ALL_EXCEPT)), - uint16_t(FE_ALL_EXCEPT & ~e)); - // After clearing, we raise the exception again. - __llvm_libc::fputil::raise_except(e); - } - - for (uint16_t e1 : excepts) { - for (uint16_t e2 : excepts) { - __llvm_libc::feclearexcept(e1 | e2); - ASSERT_EQ(uint16_t(__llvm_libc::fputil::test_except(FE_ALL_EXCEPT)), - uint16_t(FE_ALL_EXCEPT & ~(e1 | e2))); - __llvm_libc::fputil::raise_except(e1 | e2); - } - } - - for (uint16_t e1 : excepts) { - for (uint16_t e2 : excepts) { - for (uint16_t e3 : excepts) { - __llvm_libc::feclearexcept(e1 | e2 | e3); - ASSERT_EQ(uint16_t(__llvm_libc::fputil::test_except(FE_ALL_EXCEPT)), - uint16_t(FE_ALL_EXCEPT & ~(e1 | e2 | e3))); - __llvm_libc::fputil::raise_except(e1 | e2 | e3); - } - } - } - - for (uint16_t e1 : excepts) { - for (uint16_t e2 : excepts) { - for (uint16_t e3 : excepts) { - for (uint16_t e4 : excepts) { - __llvm_libc::feclearexcept(e1 | e2 | e3 | e4); - ASSERT_EQ(uint16_t(__llvm_libc::fputil::test_except(FE_ALL_EXCEPT)), - uint16_t(FE_ALL_EXCEPT & ~(e1 | e2 | e3 | e4))); - __llvm_libc::fputil::raise_except(e1 | e2 | e3 | e4); - } - } - } - } - for (uint16_t e1 : excepts) { for (uint16_t e2 : excepts) { for (uint16_t e3 : excepts) { for (uint16_t e4 : excepts) { for (uint16_t e5 : excepts) { __llvm_libc::feclearexcept(e1 | e2 | e3 | e4 | e5); - ASSERT_EQ(uint16_t(__llvm_libc::fputil::test_except(FE_ALL_EXCEPT)), - uint16_t(FE_ALL_EXCEPT & ~(e1 | e2 | e3 | e4 | e5))); + ASSERT_EQ(__llvm_libc::fputil::test_except(e1 | e2 | e3 | e4 | e5), + 0); __llvm_libc::fputil::raise_except(e1 | e2 | e3 | e4 | e5); } } diff --git a/libc/test/src/fenv/feholdexcept_test.cpp b/libc/test/src/fenv/feholdexcept_test.cpp --- a/libc/test/src/fenv/feholdexcept_test.cpp +++ b/libc/test/src/fenv/feholdexcept_test.cpp @@ -8,7 +8,7 @@ #include "src/fenv/feholdexcept.h" -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/architectures.h" #include "utils/UnitTest/FPExceptMatcher.h" #include "utils/UnitTest/Test.h" diff --git a/libc/test/src/fenv/feupdateenv_test.cpp b/libc/test/src/fenv/feupdateenv_test.cpp --- a/libc/test/src/fenv/feupdateenv_test.cpp +++ b/libc/test/src/fenv/feupdateenv_test.cpp @@ -8,7 +8,7 @@ #include "src/fenv/feupdateenv.h" -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "utils/UnitTest/Test.h" #include diff --git a/libc/test/src/fenv/getenv_and_setenv_test.cpp b/libc/test/src/fenv/getenv_and_setenv_test.cpp --- a/libc/test/src/fenv/getenv_and_setenv_test.cpp +++ b/libc/test/src/fenv/getenv_and_setenv_test.cpp @@ -11,7 +11,7 @@ #include "src/fenv/fesetenv.h" #include "src/fenv/fesetround.h" -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "utils/UnitTest/Test.h" #include diff --git a/libc/test/src/math/RIntTest.h b/libc/test/src/math/RIntTest.h --- a/libc/test/src/math/RIntTest.h +++ b/libc/test/src/math/RIntTest.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_TEST_SRC_MATH_RINTTEST_H #define LLVM_LIBC_TEST_SRC_MATH_RINTTEST_H -#include "src/__support/FPUtil/FEnvUtils.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FPBits.h" #include "utils/MPFRWrapper/MPFRUtils.h" #include "utils/UnitTest/FPMatcher.h" diff --git a/libc/test/src/math/RoundToIntegerTest.h b/libc/test/src/math/RoundToIntegerTest.h --- a/libc/test/src/math/RoundToIntegerTest.h +++ b/libc/test/src/math/RoundToIntegerTest.h @@ -9,17 +9,13 @@ #ifndef LLVM_LIBC_TEST_SRC_MATH_ROUNDTOINTEGERTEST_H #define LLVM_LIBC_TEST_SRC_MATH_ROUNDTOINTEGERTEST_H +#include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FPBits.h" #include "utils/MPFRWrapper/MPFRUtils.h" #include "utils/UnitTest/Test.h" -#include -#if math_errhandling & MATH_ERRNO #include -#endif -#if math_errhandling & MATH_ERREXCEPT -#include "src/__support/FPUtil/FEnvUtils.h" -#endif +#include namespace mpfr = __llvm_libc::testing::mpfr; @@ -42,32 +38,28 @@ const F nan = F(__llvm_libc::fputil::FPBits::build_nan(1)); static constexpr I INTEGER_MIN = I(1) << (sizeof(I) * 8 - 1); static constexpr I INTEGER_MAX = -(INTEGER_MIN + 1); + const bool errno_test = math_errhandling & MATH_ERRNO; + const bool errexcept_test = math_errhandling & MATH_ERREXCEPT; void test_one_input(RoundToIntegerFunc func, F input, I expected, bool expectError) { -#if math_errhandling & MATH_ERRNO - errno = 0; -#endif -#if math_errhandling & MATH_ERREXCEPT - __llvm_libc::fputil::clear_except(FE_ALL_EXCEPT); -#endif + if (errno_test) + errno = 0; + if (errexcept_test) + __llvm_libc::fputil::clear_except(FE_ALL_EXCEPT); ASSERT_EQ(func(input), expected); if (expectError) { -#if math_errhandling & MATH_ERREXCEPT - ASSERT_EQ(__llvm_libc::fputil::test_except(FE_ALL_EXCEPT), FE_INVALID); -#endif -#if math_errhandling & MATH_ERRNO - ASSERT_EQ(errno, EDOM); -#endif + if (errexcept_test) + ASSERT_EQ(__llvm_libc::fputil::test_except(FE_ALL_EXCEPT), FE_INVALID); + if (errno_test) + ASSERT_EQ(errno, EDOM); } else { -#if math_errhandling & MATH_ERREXCEPT - ASSERT_EQ(__llvm_libc::fputil::test_except(FE_ALL_EXCEPT), 0); -#endif -#if math_errhandling & MATH_ERRNO - ASSERT_EQ(errno, 0); -#endif + if (errexcept_test) + ASSERT_EQ(__llvm_libc::fputil::test_except(FE_ALL_EXCEPT), 0); + if (errno_test) + ASSERT_EQ(errno, 0); } } @@ -88,12 +80,12 @@ public: void SetUp() override { -#if math_errhandling & MATH_ERREXCEPT - // We will disable all exceptions so that the test will not - // crash with SIGFPE. We can still use fetestexcept to check - // if the appropriate flag was raised. - __llvm_libc::fputil::disable_except(FE_ALL_EXCEPT); -#endif + if (errexcept_test) { + // We will disable all exceptions so that the test will not + // crash with SIGFPE. We can still use fetestexcept to check + // if the appropriate flag was raised. + __llvm_libc::fputil::disable_except(FE_ALL_EXCEPT); + } } void do_infinity_and_na_n_test(RoundToIntegerFunc func) { diff --git a/libc/test/src/math/cosf_test.cpp b/libc/test/src/math/cosf_test.cpp --- a/libc/test/src/math/cosf_test.cpp +++ b/libc/test/src/math/cosf_test.cpp @@ -28,22 +28,29 @@ TEST(LlvmLibcCosfTest, SpecialNumbers) { errno = 0; + const bool errno_test = math_errhandling & MATH_ERRNO; + EXPECT_FP_EQ(aNaN, __llvm_libc::cosf(aNaN)); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); EXPECT_FP_EQ(1.0f, __llvm_libc::cosf(0.0f)); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); EXPECT_FP_EQ(1.0f, __llvm_libc::cosf(-0.0f)); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); errno = 0; EXPECT_FP_EQ(aNaN, __llvm_libc::cosf(inf)); - EXPECT_EQ(errno, EDOM); + if (errno_test) + EXPECT_EQ(errno, EDOM); errno = 0; EXPECT_FP_EQ(aNaN, __llvm_libc::cosf(neg_inf)); - EXPECT_EQ(errno, EDOM); + if (errno_test) + EXPECT_EQ(errno, EDOM); } TEST(LlvmLibcCosfTest, InFloatRange) { diff --git a/libc/test/src/math/exp2f_test.cpp b/libc/test/src/math/exp2f_test.cpp --- a/libc/test/src/math/exp2f_test.cpp +++ b/libc/test/src/math/exp2f_test.cpp @@ -23,81 +23,105 @@ TEST(LlvmLibcExp2fTest, SpecialNumbers) { errno = 0; + const bool errno_test = math_errhandling & MATH_ERRNO; + EXPECT_FP_EQ(aNaN, __llvm_libc::exp2f(aNaN)); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); EXPECT_FP_EQ(inf, __llvm_libc::exp2f(inf)); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); EXPECT_FP_EQ(0.0f, __llvm_libc::exp2f(neg_inf)); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); EXPECT_FP_EQ(1.0f, __llvm_libc::exp2f(0.0f)); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); EXPECT_FP_EQ(1.0f, __llvm_libc::exp2f(-0.0f)); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); } TEST(LlvmLibcExpfTest, Overflow) { errno = 0; + const bool errno_test = math_errhandling & MATH_ERRNO; + EXPECT_FP_EQ(inf, __llvm_libc::exp2f(float(FPBits(0x7f7fffffU)))); - EXPECT_EQ(errno, ERANGE); + if (errno_test) + EXPECT_EQ(errno, ERANGE); errno = 0; EXPECT_FP_EQ(inf, __llvm_libc::exp2f(float(FPBits(0x43000000U)))); - EXPECT_EQ(errno, ERANGE); + if (errno_test) + EXPECT_EQ(errno, ERANGE); errno = 0; EXPECT_FP_EQ(inf, __llvm_libc::exp2f(float(FPBits(0x43000001U)))); - EXPECT_EQ(errno, ERANGE); + if (errno_test) + EXPECT_EQ(errno, ERANGE); } // Test with inputs which are the borders of underflow/overflow but still // produce valid results without setting errno. TEST(LlvmLibcExpfTest, Borderline) { float x; + const bool errno_test = math_errhandling & MATH_ERRNO; errno = 0; x = float(FPBits(0x42fa0001U)); EXPECT_MPFR_MATCH(mpfr::Operation::Exp2, x, __llvm_libc::exp2f(x), 1.0); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); x = float(FPBits(0x42ffffffU)); EXPECT_MPFR_MATCH(mpfr::Operation::Exp2, x, __llvm_libc::exp2f(x), 1.0); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); x = float(FPBits(0xc2fa0001U)); EXPECT_MPFR_MATCH(mpfr::Operation::Exp2, x, __llvm_libc::exp2f(x), 1.0); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); x = float(FPBits(0xc2fc0000U)); EXPECT_MPFR_MATCH(mpfr::Operation::Exp2, x, __llvm_libc::exp2f(x), 1.0); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); x = float(FPBits(0xc2fc0001U)); EXPECT_MPFR_MATCH(mpfr::Operation::Exp2, x, __llvm_libc::exp2f(x), 1.0); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); x = float(FPBits(0xc3150000U)); EXPECT_MPFR_MATCH(mpfr::Operation::Exp2, x, __llvm_libc::exp2f(x), 1.0); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); } TEST(LlvmLibcExpfTest, Underflow) { errno = 0; + const bool errno_test = math_errhandling & MATH_ERRNO; + EXPECT_FP_EQ(0.0f, __llvm_libc::exp2f(float(FPBits(0xff7fffffU)))); - EXPECT_EQ(errno, ERANGE); + if (errno_test) + EXPECT_EQ(errno, ERANGE); errno = 0; float x = float(FPBits(0xc3158000U)); EXPECT_MPFR_MATCH(mpfr::Operation::Exp2, x, __llvm_libc::exp2f(x), 1.0); - EXPECT_EQ(errno, ERANGE); + if (errno_test) + EXPECT_EQ(errno, ERANGE); errno = 0; x = float(FPBits(0xc3165432U)); EXPECT_MPFR_MATCH(mpfr::Operation::Exp2, x, __llvm_libc::exp2f(x), 1.0); - EXPECT_EQ(errno, ERANGE); + if (errno_test) + EXPECT_EQ(errno, ERANGE); } TEST(LlvmLibcexp2fTest, InFloatRange) { diff --git a/libc/test/src/math/expf_test.cpp b/libc/test/src/math/expf_test.cpp --- a/libc/test/src/math/expf_test.cpp +++ b/libc/test/src/math/expf_test.cpp @@ -23,73 +23,95 @@ TEST(LlvmLibcExpfTest, SpecialNumbers) { errno = 0; + const bool errno_test = math_errhandling & MATH_ERRNO; + EXPECT_FP_EQ(aNaN, __llvm_libc::expf(aNaN)); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); EXPECT_FP_EQ(inf, __llvm_libc::expf(inf)); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); EXPECT_FP_EQ(0.0f, __llvm_libc::expf(neg_inf)); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); EXPECT_FP_EQ(1.0f, __llvm_libc::expf(0.0f)); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); EXPECT_FP_EQ(1.0f, __llvm_libc::expf(-0.0f)); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); } TEST(LlvmLibcExpfTest, Overflow) { + const bool errno_test = math_errhandling & MATH_ERRNO; + errno = 0; EXPECT_FP_EQ(inf, __llvm_libc::expf(float(FPBits(0x7f7fffffU)))); - EXPECT_EQ(errno, ERANGE); + if (errno_test) + EXPECT_EQ(errno, ERANGE); errno = 0; EXPECT_FP_EQ(inf, __llvm_libc::expf(float(FPBits(0x42cffff8U)))); - EXPECT_EQ(errno, ERANGE); + if (errno_test) + EXPECT_EQ(errno, ERANGE); errno = 0; EXPECT_FP_EQ(inf, __llvm_libc::expf(float(FPBits(0x42d00008U)))); - EXPECT_EQ(errno, ERANGE); + if (errno_test) + EXPECT_EQ(errno, ERANGE); } TEST(LlvmLibcExpfTest, Underflow) { + const bool errno_test = math_errhandling & MATH_ERRNO; + errno = 0; EXPECT_FP_EQ(0.0f, __llvm_libc::expf(float(FPBits(0xff7fffffU)))); - EXPECT_EQ(errno, ERANGE); + if (errno_test) + EXPECT_EQ(errno, ERANGE); errno = 0; float x = float(FPBits(0xc2cffff8U)); EXPECT_MPFR_MATCH(mpfr::Operation::Exp, x, __llvm_libc::expf(x), 1.0); - EXPECT_EQ(errno, ERANGE); + if (errno_test) + EXPECT_EQ(errno, ERANGE); errno = 0; x = float(FPBits(0xc2d00008U)); EXPECT_MPFR_MATCH(mpfr::Operation::Exp, x, __llvm_libc::expf(x), 1.0); - EXPECT_EQ(errno, ERANGE); + if (errno_test) + EXPECT_EQ(errno, ERANGE); } // Test with inputs which are the borders of underflow/overflow but still // produce valid results without setting errno. TEST(LlvmLibcExpfTest, Borderline) { float x; + const bool errno_test = math_errhandling & MATH_ERRNO; errno = 0; x = float(FPBits(0x42affff8U)); ASSERT_MPFR_MATCH(mpfr::Operation::Exp, x, __llvm_libc::expf(x), 1.0); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); x = float(FPBits(0x42b00008U)); ASSERT_MPFR_MATCH(mpfr::Operation::Exp, x, __llvm_libc::expf(x), 1.0); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); x = float(FPBits(0xc2affff8U)); ASSERT_MPFR_MATCH(mpfr::Operation::Exp, x, __llvm_libc::expf(x), 1.0); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); x = float(FPBits(0xc2b00008U)); ASSERT_MPFR_MATCH(mpfr::Operation::Exp, x, __llvm_libc::expf(x), 1.0); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); } TEST(LlvmLibcExpfTest, InFloatRange) { diff --git a/libc/test/src/math/expm1f_test.cpp b/libc/test/src/math/expm1f_test.cpp --- a/libc/test/src/math/expm1f_test.cpp +++ b/libc/test/src/math/expm1f_test.cpp @@ -21,75 +21,98 @@ DECLARE_SPECIAL_CONSTANTS(float) TEST(LlvmLibcExpm1fTest, SpecialNumbers) { + const bool errno_test = math_errhandling & MATH_ERRNO; + errno = 0; EXPECT_FP_EQ(aNaN, __llvm_libc::expm1f(aNaN)); - EXPECT_EQ(errno, 0); + if (errno_test) + if (errno_test) + EXPECT_EQ(errno, 0); EXPECT_FP_EQ(inf, __llvm_libc::expm1f(inf)); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); EXPECT_FP_EQ(-1.0f, __llvm_libc::expm1f(neg_inf)); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); EXPECT_FP_EQ(0.0f, __llvm_libc::expm1f(0.0f)); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); EXPECT_FP_EQ(-0.0f, __llvm_libc::expm1f(-0.0f)); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); } TEST(LlvmLibcExpm1fTest, Overflow) { + const bool errno_test = math_errhandling & MATH_ERRNO; + errno = 0; EXPECT_FP_EQ(inf, __llvm_libc::expm1f(float(FPBits(0x7f7fffffU)))); - EXPECT_EQ(errno, ERANGE); + if (errno_test) + EXPECT_EQ(errno, ERANGE); errno = 0; EXPECT_FP_EQ(inf, __llvm_libc::expm1f(float(FPBits(0x42cffff8U)))); - EXPECT_EQ(errno, ERANGE); + if (errno_test) + EXPECT_EQ(errno, ERANGE); errno = 0; EXPECT_FP_EQ(inf, __llvm_libc::expm1f(float(FPBits(0x42d00008U)))); - EXPECT_EQ(errno, ERANGE); + if (errno_test) + EXPECT_EQ(errno, ERANGE); } TEST(LlvmLibcExpm1fTest, Underflow) { + const bool errno_test = math_errhandling & MATH_ERRNO; + errno = 0; EXPECT_FP_EQ(-1.0f, __llvm_libc::expm1f(float(FPBits(0xff7fffffU)))); - EXPECT_EQ(errno, ERANGE); + if (errno_test) + EXPECT_EQ(errno, ERANGE); errno = 0; float x = float(FPBits(0xc2cffff8U)); EXPECT_FP_EQ(-1.0f, __llvm_libc::expm1f(x)); - EXPECT_EQ(errno, ERANGE); + if (errno_test) + EXPECT_EQ(errno, ERANGE); errno = 0; x = float(FPBits(0xc2d00008U)); EXPECT_FP_EQ(-1.0f, __llvm_libc::expm1f(x)); - EXPECT_EQ(errno, ERANGE); + if (errno_test) + EXPECT_EQ(errno, ERANGE); } // Test with inputs which are the borders of underflow/overflow but still // produce valid results without setting errno. TEST(LlvmLibcExpm1fTest, Borderline) { float x; + const bool errno_test = math_errhandling & MATH_ERRNO; errno = 0; x = float(FPBits(0x42affff8U)); ASSERT_MPFR_MATCH(mpfr::Operation::Expm1, x, __llvm_libc::expm1f(x), 1.0); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); x = float(FPBits(0x42b00008U)); ASSERT_MPFR_MATCH(mpfr::Operation::Expm1, x, __llvm_libc::expm1f(x), 1.0); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); x = float(FPBits(0xc2affff8U)); ASSERT_MPFR_MATCH(mpfr::Operation::Expm1, x, __llvm_libc::expm1f(x), 1.0); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); x = float(FPBits(0xc2b00008U)); ASSERT_MPFR_MATCH(mpfr::Operation::Expm1, x, __llvm_libc::expm1f(x), 1.0); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); } TEST(LlvmLibcExpm1fTest, InFloatRange) { diff --git a/libc/test/src/math/sincosf_test.cpp b/libc/test/src/math/sincosf_test.cpp --- a/libc/test/src/math/sincosf_test.cpp +++ b/libc/test/src/math/sincosf_test.cpp @@ -29,32 +29,39 @@ errno = 0; float sin, cos; + const bool errno_test = math_errhandling & MATH_ERRNO; + __llvm_libc::sincosf(aNaN, &sin, &cos); EXPECT_FP_EQ(aNaN, cos); EXPECT_FP_EQ(aNaN, sin); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); __llvm_libc::sincosf(0.0f, &sin, &cos); EXPECT_FP_EQ(1.0f, cos); EXPECT_FP_EQ(0.0f, sin); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); __llvm_libc::sincosf(-0.0f, &sin, &cos); EXPECT_FP_EQ(1.0f, cos); EXPECT_FP_EQ(-0.0f, sin); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); errno = 0; __llvm_libc::sincosf(inf, &sin, &cos); EXPECT_FP_EQ(aNaN, cos); EXPECT_FP_EQ(aNaN, sin); - EXPECT_EQ(errno, EDOM); + if (errno_test) + EXPECT_EQ(errno, EDOM); errno = 0; __llvm_libc::sincosf(neg_inf, &sin, &cos); EXPECT_FP_EQ(aNaN, cos); EXPECT_FP_EQ(aNaN, sin); - EXPECT_EQ(errno, EDOM); + if (errno_test) + EXPECT_EQ(errno, EDOM); } TEST(LlvmLibcSinCosfTest, InFloatRange) { diff --git a/libc/test/src/math/sinf_test.cpp b/libc/test/src/math/sinf_test.cpp --- a/libc/test/src/math/sinf_test.cpp +++ b/libc/test/src/math/sinf_test.cpp @@ -28,22 +28,29 @@ TEST(LlvmLibcSinfTest, SpecialNumbers) { errno = 0; + const bool errno_test = math_errhandling & MATH_ERRNO; + EXPECT_FP_EQ(aNaN, __llvm_libc::sinf(aNaN)); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); EXPECT_FP_EQ(0.0f, __llvm_libc::sinf(0.0f)); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); EXPECT_FP_EQ(-0.0f, __llvm_libc::sinf(-0.0f)); - EXPECT_EQ(errno, 0); + if (errno_test) + EXPECT_EQ(errno, 0); errno = 0; EXPECT_FP_EQ(aNaN, __llvm_libc::sinf(inf)); - EXPECT_EQ(errno, EDOM); + if (errno_test) + EXPECT_EQ(errno, EDOM); errno = 0; EXPECT_FP_EQ(aNaN, __llvm_libc::sinf(neg_inf)); - EXPECT_EQ(errno, EDOM); + if (errno_test) + EXPECT_EQ(errno, EDOM); } TEST(LlvmLibcSinfTest, InFloatRange) { diff --git a/libc/test/src/stdlib/strtold_test.cpp b/libc/test/src/stdlib/strtold_test.cpp --- a/libc/test/src/stdlib/strtold_test.cpp +++ b/libc/test/src/stdlib/strtold_test.cpp @@ -175,12 +175,12 @@ TEST_F(LlvmLibcStrToLDTest, ComplexHexadecimalTests) { run_test("0x1p16383", 9, 0x7ff0000000000000, (__uint128_t(0x7ffe800000) << 40), - (__uint128_t(0x7ffe000000000000) << 64)); + (__uint128_t(0x7ffe000000000000) << 64), ERANGE); run_test("0x123456789abcdef", 17, 0x43723456789abcdf, (__uint128_t(0x403791a2b3) << 40) + __uint128_t(0xc4d5e6f780), (__uint128_t(0x403723456789abcd) << 64) + __uint128_t(0xef00000000000000)); - run_test("0x123456789abcdef0123456789ABCDEF", 33, 0x7ff0000000000000, + run_test("0x123456789abcdef0123456789ABCDEF", 33, 0x47723456789abcdf, (__uint128_t(0x407791a2b3) << 40) + __uint128_t(0xc4d5e6f781), (__uint128_t(0x407723456789abcd) << 64) + __uint128_t(0xef0123456789abce));