Skip to content

[libc][c23][fenv] Implement fetestexceptflag #87828

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libc/config/baremetal/arm/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.fenv.fesetround
libc.src.fenv.feraiseexcept
libc.src.fenv.fetestexcept
libc.src.fenv.fetestexceptflag
libc.src.fenv.feupdateenv

# math.h entrypoints
Expand Down
1 change: 1 addition & 0 deletions libc/config/baremetal/riscv/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.fenv.fesetround
libc.src.fenv.feraiseexcept
libc.src.fenv.fetestexcept
libc.src.fenv.fetestexceptflag
libc.src.fenv.feupdateenv

# math.h entrypoints
Expand Down
1 change: 1 addition & 0 deletions libc/config/darwin/arm/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.fenv.fesetround
libc.src.fenv.feraiseexcept
libc.src.fenv.fetestexcept
libc.src.fenv.fetestexceptflag
libc.src.fenv.feupdateenv

# math.h entrypoints
Expand Down
1 change: 1 addition & 0 deletions libc/config/darwin/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ set(TARGET_LIBM_ENTRYPOINTS
# libc.src.fenv.fesetround
# libc.src.fenv.feraiseexcept
# libc.src.fenv.fetestexcept
# libc.src.fenv.fetestexceptflag
# libc.src.fenv.feupdateenv

## Currently disabled for failing tests.
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/aarch64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.fenv.fesetround
libc.src.fenv.feraiseexcept
libc.src.fenv.fetestexcept
libc.src.fenv.fetestexceptflag
libc.src.fenv.feupdateenv

# math.h entrypoints
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/arm/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.fenv.fesetround
libc.src.fenv.feraiseexcept
libc.src.fenv.fetestexcept
libc.src.fenv.fetestexceptflag
libc.src.fenv.feupdateenv

# math.h entrypoints
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/riscv/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.fenv.fesetround
libc.src.fenv.feraiseexcept
libc.src.fenv.fetestexcept
libc.src.fenv.fetestexceptflag
libc.src.fenv.feupdateenv

# math.h entrypoints
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.fenv.fesetround
libc.src.fenv.feraiseexcept
libc.src.fenv.fetestexcept
libc.src.fenv.fetestexceptflag
libc.src.fenv.feupdateenv

# math.h entrypoints
Expand Down
1 change: 1 addition & 0 deletions libc/config/windows/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.fenv.fesetround
libc.src.fenv.feraiseexcept
libc.src.fenv.fetestexcept
libc.src.fenv.fetestexceptflag
libc.src.fenv.feupdateenv

# math.h entrypoints
Expand Down
2 changes: 1 addition & 1 deletion libc/docs/c23.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Additions:
* fenv.h

* fesetexcept |check|
* fetestexceptflag
* fetestexceptflag |check|
* fegetmode
* fesetmode
* math.h
Expand Down
4 changes: 2 additions & 2 deletions libc/docs/fenv.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ fenv.h Functions
- |check|
- 7.6.6.3
* - fesetexcept
-
- |check|
- 7.6.4.4
* - fesetexceptflag
- |check|
Expand All @@ -57,7 +57,7 @@ fenv.h Functions
- |check|
- 7.6.4.7
* - fetestexceptflag
-
- |check|
- 7.6.4.6
* - feupdateenv
- |check|
Expand Down
5 changes: 5 additions & 0 deletions libc/spec/stdc.td
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,11 @@ def StdC : StandardSpec<"stdc"> {
RetValSpec<IntType>,
[ArgSpec<IntType>]
>,
FunctionSpec<
"fetestexceptflag",
RetValSpec<IntType>,
[ArgSpec<ConstFExceptTPtr>, ArgSpec<IntType>]
>,
FunctionSpec<
"feraiseexcept",
RetValSpec<IntType>,
Expand Down
13 changes: 13 additions & 0 deletions libc/src/fenv/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,19 @@ add_entrypoint_object(
-O2
)

add_entrypoint_object(
fetestexceptflag
SRCS
fetestexceptflag.cpp
HDRS
fetestexceptflag.h
DEPENDS
libc.hdr.types.fexcept_t
libc.src.__support.FPUtil.fenv_impl
COMPILE_OPTIONS
-O2
)

add_entrypoint_object(
fegetenv
SRCS
Expand Down
23 changes: 23 additions & 0 deletions libc/src/fenv/fetestexceptflag.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//===-- Implementation of fetestexceptflag 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/fetestexceptflag.h"
#include "hdr/types/fexcept_t.h"
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/common.h"

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(int, fetestexceptflag,
(const fexcept_t *flagp, int excepts)) {
static_assert(sizeof(int) >= sizeof(fexcept_t),
"fexcept_t value cannot fit in an int value.");
return *flagp | fputil::test_except(excepts);
}

} // namespace LIBC_NAMESPACE
20 changes: 20 additions & 0 deletions libc/src/fenv/fetestexceptflag.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation header for fetestexceptflag --------------*- 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_FETESTEXCEPTFLAG_H
#define LLVM_LIBC_SRC_FENV_FETESTEXCEPTFLAG_H

#include "hdr/types/fexcept_t.h"

namespace LIBC_NAMESPACE {

int fetestexceptflag(const fexcept_t *, int excepts);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_FENV_FETESTEXCEPTFLAG_H
1 change: 1 addition & 0 deletions libc/test/src/fenv/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ add_libc_unittest(
DEPENDS
libc.src.fenv.fegetexceptflag
libc.src.fenv.fesetexceptflag
libc.src.fenv.fetestexceptflag
libc.src.__support.FPUtil.fenv_impl
)

Expand Down
32 changes: 25 additions & 7 deletions libc/test/src/fenv/exception_flags_test.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//===-- Unittests for fegetexceptflag and fesetexceptflag -----------------===//
//===-- Unittests for fe{get|set|test}exceptflag --------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
Expand All @@ -9,11 +9,12 @@
#include "hdr/types/fexcept_t.h"
#include "src/fenv/fegetexceptflag.h"
#include "src/fenv/fesetexceptflag.h"
#include "src/fenv/fetestexceptflag.h"

#include "src/__support/FPUtil/FEnvImpl.h"
#include "test/UnitTest/Test.h"

TEST(LlvmLibcFenvTest, GetExceptFlagAndSetExceptFlag) {
TEST(LlvmLibcFenvTest, GetSetTestExceptFlag) {
// We will disable all exceptions to prevent invocation of the exception
// handler.
LIBC_NAMESPACE::fputil::disable_except(FE_ALL_EXCEPT);
Expand All @@ -39,19 +40,36 @@ TEST(LlvmLibcFenvTest, GetExceptFlagAndSetExceptFlag) {
ASSERT_EQ(LIBC_NAMESPACE::fesetexceptflag(&eflags, FE_ALL_EXCEPT), 0);
ASSERT_NE(LIBC_NAMESPACE::fputil::test_except(FE_ALL_EXCEPT) & e, 0);

// Exception flags are exactly the flags corresponding to the previously
// raised exception.
ASSERT_EQ(LIBC_NAMESPACE::fetestexceptflag(&eflags, FE_ALL_EXCEPT),
LIBC_NAMESPACE::fputil::test_except(FE_ALL_EXCEPT));

// Cleanup. We clear all excepts as raising excepts like FE_OVERFLOW
// can also raise FE_INEXACT.
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
}

// Next, we will raise one exception and save the flags.
// Next, we will raise one exception, save the flag and clear all exceptions.
LIBC_NAMESPACE::fputil::raise_except(FE_INVALID);
fexcept_t eflags;
LIBC_NAMESPACE::fegetexceptflag(&eflags, FE_ALL_EXCEPT);
// Clear all exceptions and raise two other exceptions.
fexcept_t invalid_flag;
LIBC_NAMESPACE::fegetexceptflag(&invalid_flag, FE_ALL_EXCEPT);
ASSERT_EQ(LIBC_NAMESPACE::fetestexceptflag(&invalid_flag, FE_ALL_EXCEPT),
FE_INVALID);
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);

// Raise two other exceptions and verify that they are set.
LIBC_NAMESPACE::fputil::raise_except(FE_OVERFLOW | FE_INEXACT);
fexcept_t overflow_and_inexact_flag;
LIBC_NAMESPACE::fegetexceptflag(&overflow_and_inexact_flag, FE_ALL_EXCEPT);
ASSERT_EQ(LIBC_NAMESPACE::fetestexceptflag(&overflow_and_inexact_flag,
FE_ALL_EXCEPT),
FE_OVERFLOW | FE_INEXACT);
ASSERT_EQ(LIBC_NAMESPACE::fetestexceptflag(&overflow_and_inexact_flag,
FE_OVERFLOW | FE_INEXACT),
FE_OVERFLOW | FE_INEXACT);

// When we set the flags and test, we should only see FE_INVALID.
LIBC_NAMESPACE::fesetexceptflag(&eflags, FE_ALL_EXCEPT);
LIBC_NAMESPACE::fesetexceptflag(&invalid_flag, FE_ALL_EXCEPT);
EXPECT_EQ(LIBC_NAMESPACE::fputil::test_except(FE_ALL_EXCEPT), FE_INVALID);
}
10 changes: 10 additions & 0 deletions utils/bazel/llvm-project-overlay/libc/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -1145,6 +1145,16 @@ libc_function(
],
)

libc_function(
name = "fetestexceptflag",
srcs = ["src/fenv/fetestexceptflag.cpp"],
hdrs = ["src/fenv/fetestexceptflag.h"],
deps = [
":__support_common",
":__support_fputil_fenv_impl",
],
)

libc_function(
name = "feclearexcept",
srcs = ["src/fenv/feclearexcept.cpp"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ libc_test(
libc_function_deps = [
"//libc:fegetexceptflag",
"//libc:fesetexceptflag",
"//libc:fetestexceptflag",
],
deps = [
"//libc:__support_fputil_fenv_impl",
Expand Down