| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| //===-- Implementation of fesetexceptflag 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/fenv/fesetexceptflag.h" | ||
| #include "src/__support/common.h" | ||
| #include "utils/FPUtil/FEnv.h" | ||
|
|
||
| #include <fenv.h> | ||
|
|
||
| namespace __llvm_libc { | ||
|
|
||
| LLVM_LIBC_FUNCTION(int, fesetexceptflag, | ||
| (const fexcept_t *flagp, int excepts)) { | ||
| // Since the return type of fetestexcept is int, we ensure that fexcept_t | ||
| // matches in size. | ||
| static_assert(sizeof(int) == sizeof(fexcept_t), | ||
| "sizeof(fexcept_t) != sizeof(int)"); | ||
| int excepts_to_set = *reinterpret_cast<const int *>(flagp) & excepts; | ||
| return fputil::setExcept(excepts_to_set); | ||
| } | ||
|
|
||
| } // namespace __llvm_libc |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| //===-- Implementation header for fesetexceptflag ---------------*- 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_FENV_FESETEXCEPTFLAG_H | ||
| #define LLVM_LIBC_SRC_FENV_FESETEXCEPTFLAG_H | ||
|
|
||
| #include <fenv.h> | ||
|
|
||
| namespace __llvm_libc { | ||
|
|
||
| int fesetexceptflag(const fexcept_t *, int excepts); | ||
|
|
||
| } // namespace __llvm_libc | ||
|
|
||
| #endif // LLVM_LIBC_SRC_FENV_FESETEXCEPTFLAG_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| //===-- Implementation of feupdateenv 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/fenv/feupdateenv.h" | ||
| #include "src/__support/common.h" | ||
| #include "utils/FPUtil/FEnv.h" | ||
|
|
||
| #include <fenv.h> | ||
|
|
||
| namespace __llvm_libc { | ||
|
|
||
| LLVM_LIBC_FUNCTION(int, feupdateenv, (const fenv_t *envp)) { | ||
| int current_excepts = fputil::testExcept(FE_ALL_EXCEPT); | ||
| if (fputil::setEnv(envp) != 0) | ||
| return -1; | ||
| return fputil::raiseExcept(current_excepts); | ||
| } | ||
|
|
||
| } // namespace __llvm_libc |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| //===-- Implementation header for feupdateenv -------------------*- 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_FENV_FEUPDATEENV_H | ||
| #define LLVM_LIBC_SRC_FENV_FEUPDATEENV_H | ||
|
|
||
| #include <fenv.h> | ||
|
|
||
| namespace __llvm_libc { | ||
|
|
||
| int feupdateenv(const fenv_t *); | ||
|
|
||
| } // namespace __llvm_libc | ||
|
|
||
| #endif // LLVM_LIBC_SRC_FENV_FEUPDATEENV_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| //===-- Unittests for fegetexceptflag and fesetexceptflag -----------------===// | ||
| // | ||
| // 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/fenv/fegetexceptflag.h" | ||
| #include "src/fenv/fesetexceptflag.h" | ||
|
|
||
| #include "utils/FPUtil/FEnv.h" | ||
| #include "utils/UnitTest/Test.h" | ||
|
|
||
| #include <fenv.h> | ||
|
|
||
| TEST(LlvmLibcFenvTest, GetExceptFlagAndSetExceptFlag) { | ||
| // We will disable all exceptions to prevent invocation of the exception | ||
| // handler. | ||
| __llvm_libc::fputil::disableExcept(FE_ALL_EXCEPT); | ||
|
|
||
| int excepts[] = {FE_DIVBYZERO, FE_INVALID, FE_INEXACT, FE_OVERFLOW, | ||
| FE_UNDERFLOW}; | ||
|
|
||
| for (int e : excepts) { | ||
| // The overall idea is to raise an except and save the exception flags. | ||
| // Next, clear the flags and then set the saved exception flags. This | ||
| // should set the flag corresponding to the previously raised exception. | ||
| __llvm_libc::fputil::raiseExcept(e); | ||
| // Make sure that the exception flag is set. | ||
| ASSERT_NE(__llvm_libc::fputil::testExcept(FE_ALL_EXCEPT) & e, 0); | ||
|
|
||
| fexcept_t eflags; | ||
| ASSERT_EQ(__llvm_libc::fegetexceptflag(&eflags, FE_ALL_EXCEPT), 0); | ||
|
|
||
| __llvm_libc::fputil::clearExcept(e); | ||
| ASSERT_EQ(__llvm_libc::fputil::testExcept(FE_ALL_EXCEPT) & e, 0); | ||
|
|
||
| ASSERT_EQ(__llvm_libc::fesetexceptflag(&eflags, FE_ALL_EXCEPT), 0); | ||
| ASSERT_NE(__llvm_libc::fputil::testExcept(FE_ALL_EXCEPT) & e, 0); | ||
|
|
||
| // Cleanup | ||
| __llvm_libc::fputil::clearExcept(e); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| //===-- Unittests for feholdexcept with exceptions enabled ----------------===// | ||
| // | ||
| // 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/fenv/feholdexcept.h" | ||
|
|
||
| #include "utils/FPUtil/FEnv.h" | ||
| #include "utils/UnitTest/Test.h" | ||
|
|
||
| #include <fenv.h> | ||
| #include <signal.h> | ||
|
|
||
| TEST(LlvmLibcFEnvTest, RaiseAndCrash) { | ||
| int excepts[] = {FE_DIVBYZERO, FE_INVALID, FE_INEXACT, FE_OVERFLOW, | ||
| FE_UNDERFLOW}; | ||
|
|
||
| for (int e : excepts) { | ||
| fenv_t env; | ||
| __llvm_libc::fputil::disableExcept(FE_ALL_EXCEPT); | ||
| __llvm_libc::fputil::enableExcept(e); | ||
| ASSERT_EQ(__llvm_libc::fputil::clearExcept(FE_ALL_EXCEPT), 0); | ||
| ASSERT_EQ(__llvm_libc::feholdexcept(&env), 0); | ||
| // feholdexcept should disable all excepts so raising an exception | ||
| // should not crash/invoke the exception handler. | ||
| ASSERT_EQ(__llvm_libc::fputil::raiseExcept(e), 0); | ||
|
|
||
| // When we put back the saved env which has the exception enabled, it | ||
| // should crash with SIGFPE. | ||
| __llvm_libc::fputil::setEnv(&env); | ||
| ASSERT_DEATH([=] { __llvm_libc::fputil::raiseExcept(e); }, | ||
| WITH_SIGNAL(SIGFPE)); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| //===-- Unittests for feupdateenv -----------------------------------------===// | ||
| // | ||
| // 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/fenv/feupdateenv.h" | ||
|
|
||
| #include "utils/FPUtil/FEnv.h" | ||
| #include "utils/UnitTest/Test.h" | ||
|
|
||
| #include <fenv.h> | ||
| #include <signal.h> | ||
|
|
||
| TEST(LlvmLibcFEnvTest, UpdateEnvTest) { | ||
| __llvm_libc::fputil::disableExcept(FE_ALL_EXCEPT); | ||
| __llvm_libc::fputil::clearExcept(FE_ALL_EXCEPT); | ||
|
|
||
| fenv_t env; | ||
| ASSERT_EQ(__llvm_libc::fputil::getEnv(&env), 0); | ||
| __llvm_libc::fputil::setExcept(FE_INVALID | FE_INEXACT); | ||
| ASSERT_EQ(__llvm_libc::feupdateenv(&env), 0); | ||
| ASSERT_EQ(__llvm_libc::fputil::testExcept(FE_INVALID | FE_INEXACT), | ||
| FE_INVALID | FE_INEXACT); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| //===-- Unittests for fegetenv and fesetenv -------------------------------===// | ||
| // | ||
| // 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/fenv/fegetenv.h" | ||
| #include "src/fenv/fesetenv.h" | ||
|
|
||
| #include "utils/FPUtil/FEnv.h" | ||
| #include "utils/UnitTest/Test.h" | ||
|
|
||
| #include <fenv.h> | ||
|
|
||
| TEST(LlvmLibcFenvTest, GetEnvAndSetEnv) { | ||
| // We will disable all exceptions to prevent invocation of the exception | ||
| // handler. | ||
| __llvm_libc::fputil::disableExcept(FE_ALL_EXCEPT); | ||
|
|
||
| int excepts[] = {FE_DIVBYZERO, FE_INVALID, FE_INEXACT, FE_OVERFLOW, | ||
| FE_UNDERFLOW}; | ||
|
|
||
| for (int e : excepts) { | ||
| __llvm_libc::fputil::clearExcept(FE_ALL_EXCEPT); | ||
|
|
||
| // Save the cleared environment. | ||
| fenv_t env; | ||
| ASSERT_EQ(__llvm_libc::fegetenv(&env), 0); | ||
|
|
||
| __llvm_libc::fputil::raiseExcept(e); | ||
| // Make sure that the exception is raised. | ||
| ASSERT_NE(__llvm_libc::fputil::testExcept(FE_ALL_EXCEPT) & e, 0); | ||
|
|
||
| ASSERT_EQ(__llvm_libc::fesetenv(&env), 0); | ||
| ASSERT_EQ(__llvm_libc::fputil::testExcept(FE_ALL_EXCEPT) & e, 0); | ||
| } | ||
| } |