Initialize FreeBSD support. Currently, only overlay build (mainly math routines) is supported. This PR mainly define the target entrypoints and basic syscall support. Different from Linux, FreeBSD's syscall return always consist of two component: - return value as arch register - error flag On x86-64, the flag is returned via the carry bit state. Hence, for syscall stubs, we always return a structure containing these two fields. For math support, the only big difference is that FreeBSD has different naming convention in some exception macros. Further fixes for C++ userland are tracked in #197605 Assisted-by: Codex with gpt-5.5 high fast
69 lines
1.8 KiB
C++
69 lines
1.8 KiB
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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
///
|
|
/// \file
|
|
/// FPExceptMatchers.cpp.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#undef LIBC_MATH_USE_SYSTEM_FENV
|
|
|
|
#include "FPExceptMatcher.h"
|
|
|
|
#include "src/__support/macros/config.h"
|
|
#include "test/UnitTest/ExecuteFunction.h" // FunctionCaller
|
|
#include "test/UnitTest/Test.h"
|
|
|
|
#include "hdr/types/fenv_t.h"
|
|
#include "src/__support/FPUtil/FEnvImpl.h"
|
|
#include <setjmp.h>
|
|
#include <signal.h>
|
|
|
|
#if LIBC_TEST_HAS_MATCHERS()
|
|
|
|
namespace LIBC_NAMESPACE_DECL {
|
|
namespace testing {
|
|
|
|
#if defined(_WIN32)
|
|
#define sigjmp_buf jmp_buf
|
|
#define sigsetjmp(buf, save) setjmp(buf)
|
|
#define siglongjmp(buf, val) longjmp(buf, val)
|
|
#endif
|
|
|
|
#ifdef __FreeBSD__
|
|
using sighandler_t = __sighandler_t *;
|
|
#endif
|
|
|
|
static thread_local sigjmp_buf jumpBuffer;
|
|
static thread_local bool caughtExcept;
|
|
|
|
static void sigfpeHandler([[maybe_unused]] int sig) {
|
|
caughtExcept = true;
|
|
siglongjmp(jumpBuffer, -1);
|
|
}
|
|
|
|
FPExceptMatcher::FPExceptMatcher(FunctionCaller *func) {
|
|
auto *oldSIGFPEHandler = signal(SIGFPE, &sigfpeHandler);
|
|
|
|
caughtExcept = false;
|
|
fenv_t oldEnv;
|
|
fputil::get_env(&oldEnv);
|
|
if (sigsetjmp(jumpBuffer, 1) == 0)
|
|
func->call();
|
|
delete func;
|
|
// We restore the previous floating point environment after
|
|
// the call to the function which can potentially raise SIGFPE.
|
|
fputil::set_env(&oldEnv);
|
|
signal(SIGFPE, oldSIGFPEHandler);
|
|
exceptionRaised = caughtExcept;
|
|
}
|
|
|
|
} // namespace testing
|
|
} // namespace LIBC_NAMESPACE_DECL
|
|
|
|
#endif // LIBC_TEST_HAS_MATCHERS()
|