forked from OSchip/llvm-project
[libc] Add extension functions fedisableexcept, feenableexcept and fegetexcept.
Reviewed By: michaelrj Differential Revision: https://reviews.llvm.org/D109613
This commit is contained in:
parent
09391e7e50
commit
0da5ac1a75
|
@ -62,7 +62,10 @@ set(TARGET_LIBC_ENTRYPOINTS
|
|||
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
|
||||
|
|
|
@ -62,7 +62,10 @@ set(TARGET_LIBC_ENTRYPOINTS
|
|||
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
|
||||
|
|
|
@ -41,9 +41,33 @@ def GnuExtensions : StandardSpec<"GNUExtensions"> {
|
|||
]
|
||||
>;
|
||||
|
||||
HeaderSpec FEnv = HeaderSpec<
|
||||
"fenv.h",
|
||||
[], // Macros
|
||||
[], // Types
|
||||
[], // Enumerations
|
||||
[
|
||||
FunctionSpec<
|
||||
"fedisableexcept",
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<IntType>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"feenableexcept",
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<IntType>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"fegetexcept",
|
||||
RetValSpec<IntType>,
|
||||
[]
|
||||
>
|
||||
]
|
||||
>;
|
||||
|
||||
let Headers = [
|
||||
CType,
|
||||
FEnv,
|
||||
Math,
|
||||
String,
|
||||
];
|
||||
|
|
|
@ -140,3 +140,42 @@ add_entrypoint_object(
|
|||
COMPILE_OPTIONS
|
||||
-O2
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
feenableexcept
|
||||
SRCS
|
||||
feenableexcept.cpp
|
||||
HDRS
|
||||
feenableexcept.h
|
||||
DEPENDS
|
||||
libc.include.fenv
|
||||
libc.src.__support.FPUtil.fputil
|
||||
COMPILE_OPTIONS
|
||||
-O2
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
fedisableexcept
|
||||
SRCS
|
||||
fedisableexcept.cpp
|
||||
HDRS
|
||||
fedisableexcept.h
|
||||
DEPENDS
|
||||
libc.include.fenv
|
||||
libc.src.__support.FPUtil.fputil
|
||||
COMPILE_OPTIONS
|
||||
-O2
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
fegetexcept
|
||||
SRCS
|
||||
fegetexcept.cpp
|
||||
HDRS
|
||||
fegetexcept.h
|
||||
DEPENDS
|
||||
libc.include.fenv
|
||||
libc.src.__support.FPUtil.fputil
|
||||
COMPILE_OPTIONS
|
||||
-O2
|
||||
)
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
//===-- Implementation of fedisableexcept 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/fedisableexcept.h"
|
||||
#include "src/__support/FPUtil/FEnvUtils.h"
|
||||
#include "src/__support/common.h"
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
LLVM_LIBC_FUNCTION(int, fedisableexcept, (int e)) {
|
||||
return fputil::disableExcept(e);
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,18 @@
|
|||
//===-- Implementation header for fedisableexcept ---------------*- 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_FEDISABLEEXCEPT_H
|
||||
#define LLVM_LIBC_SRC_FENV_FEDISABLEEXCEPT_H
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
int fedisableexcept(int);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_FENV_FEDISABLEEXCEPT_H
|
|
@ -0,0 +1,19 @@
|
|||
//===-- Implementation of feenableexcept 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/feenableexcept.h"
|
||||
#include "src/__support/FPUtil/FEnvUtils.h"
|
||||
#include "src/__support/common.h"
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
LLVM_LIBC_FUNCTION(int, feenableexcept, (int e)) {
|
||||
return fputil::enableExcept(e);
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,18 @@
|
|||
//===-- Implementation header for feenableexcept ----------------*- 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_FEENABLEEXCEPT_H
|
||||
#define LLVM_LIBC_SRC_FENV_FEENABLEEXCEPT_H
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
int feenableexcept(int);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_FENV_FEENABLEEXCEPT_H
|
|
@ -0,0 +1,17 @@
|
|||
//===-- Implementation of fegetexcept 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/fegetexcept.h"
|
||||
#include "src/__support/FPUtil/FEnvUtils.h"
|
||||
#include "src/__support/common.h"
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
LLVM_LIBC_FUNCTION(int, fegetexcept, ()) { return fputil::getExcept(); }
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,18 @@
|
|||
//===-- Implementation header for fegetexcept -------------------*- 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_FEGETEXCEPT_H
|
||||
#define LLVM_LIBC_SRC_FENV_FEGETEXCEPT_H
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
int fegetexcept();
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_FENV_FEGETEXCEPT_H
|
|
@ -71,6 +71,18 @@ add_libc_unittest(
|
|||
libc.src.__support.FPUtil.fputil
|
||||
)
|
||||
|
||||
add_libc_unittest(
|
||||
feenableexcept_test
|
||||
SUITE
|
||||
libc_fenv_unittests
|
||||
SRCS
|
||||
feenableexcept_test.cpp
|
||||
DEPENDS
|
||||
libc.src.fenv.fedisableexcept
|
||||
libc.src.fenv.feenableexcept
|
||||
libc.src.fenv.fegetexcept
|
||||
)
|
||||
|
||||
if (NOT (LLVM_USE_SANITIZER OR (${LIBC_TARGET_OS} STREQUAL "windows")))
|
||||
# Sanitizers don't like SIGFPE. So, we will run the
|
||||
# tests which raise SIGFPE only in non-sanitizer builds.
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
//===-- Unittests for feenableexcept -------------------------------------===//
|
||||
//
|
||||
// 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/fedisableexcept.h"
|
||||
#include "src/fenv/feenableexcept.h"
|
||||
#include "src/fenv/fegetexcept.h"
|
||||
|
||||
#include "utils/UnitTest/Test.h"
|
||||
|
||||
#include <fenv.h>
|
||||
|
||||
TEST(LlvmLibcFEnvTest, EnableTest) {
|
||||
#ifdef __aarch64__
|
||||
// Few aarch64 HW implementations do not trap exceptions. We skip this test
|
||||
// completely on such HW.
|
||||
//
|
||||
// Whether HW supports trapping exceptions or not is deduced by enabling an
|
||||
// exception and reading back to see if the exception got enabled. If the
|
||||
// exception did not get enabled, then it means that the HW does not support
|
||||
// trapping exceptions.
|
||||
__llvm_libc::fedisableexcept(FE_ALL_EXCEPT);
|
||||
__llvm_libc::feenableexcept(FE_DIVBYZERO);
|
||||
if (__llvm_libc::fegetexcept() == 0)
|
||||
return;
|
||||
#endif
|
||||
|
||||
int excepts[] = {FE_DIVBYZERO, FE_INVALID, FE_INEXACT, FE_OVERFLOW,
|
||||
FE_UNDERFLOW};
|
||||
__llvm_libc::fedisableexcept(FE_ALL_EXCEPT);
|
||||
ASSERT_EQ(0, __llvm_libc::fegetexcept());
|
||||
|
||||
for (int e : excepts) {
|
||||
__llvm_libc::feenableexcept(e);
|
||||
ASSERT_EQ(e, __llvm_libc::fegetexcept());
|
||||
__llvm_libc::fedisableexcept(e);
|
||||
}
|
||||
|
||||
for (int e1 : excepts) {
|
||||
for (int e2 : excepts) {
|
||||
__llvm_libc::feenableexcept(e1 | e2);
|
||||
ASSERT_EQ(e1 | e2, __llvm_libc::fegetexcept());
|
||||
__llvm_libc::fedisableexcept(e1 | e2);
|
||||
}
|
||||
}
|
||||
|
||||
for (int e1 : excepts) {
|
||||
for (int e2 : excepts) {
|
||||
for (int e3 : excepts) {
|
||||
__llvm_libc::feenableexcept(e1 | e2 | e3);
|
||||
ASSERT_EQ(e1 | e2 | e3, __llvm_libc::fegetexcept());
|
||||
__llvm_libc::fedisableexcept(e1 | e2 | e3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int e1 : excepts) {
|
||||
for (int e2 : excepts) {
|
||||
for (int e3 : excepts) {
|
||||
for (int e4 : excepts) {
|
||||
__llvm_libc::feenableexcept(e1 | e2 | e3 | e4);
|
||||
ASSERT_EQ(e1 | e2 | e3 | e4, __llvm_libc::fegetexcept());
|
||||
__llvm_libc::fedisableexcept(e1 | e2 | e3 | e4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int e1 : excepts) {
|
||||
for (int e2 : excepts) {
|
||||
for (int e3 : excepts) {
|
||||
for (int e4 : excepts) {
|
||||
for (int e5 : excepts) {
|
||||
__llvm_libc::feenableexcept(e1 | e2 | e3 | e4 | e5);
|
||||
ASSERT_EQ(e1 | e2 | e3 | e4 | e5, __llvm_libc::fegetexcept());
|
||||
__llvm_libc::fedisableexcept(e1 | e2 | e3 | e4 | e5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue