[libc] Add extension functions fedisableexcept, feenableexcept and fegetexcept.

Reviewed By: michaelrj

Differential Revision: https://reviews.llvm.org/D109613
This commit is contained in:
Siva Chandra Reddy 2021-09-09 19:11:54 +00:00
parent 09391e7e50
commit 0da5ac1a75
12 changed files with 276 additions and 0 deletions

View File

@ -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

View File

@ -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

View File

@ -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,
];

View File

@ -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
)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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);
}
}
}
}
}
}