[libc-commits] [libc] [libc][MacOS] Fix Darwin aarch64 fenv and sigsetjmp build support (PR #192075)
via libc-commits
libc-commits at lists.llvm.org
Tue Apr 14 08:28:46 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libc
Author: Kacper Fiedorowicz (fenze)
<details>
<summary>Changes</summary>
This patch fixes Darwin aarch64 build failures in libc around fenv and sigsetjmp support.
Before this change, the Darwin aarch64 fenv implementation did not match the public
fenv_t layout and referenced several Darwin-specific exception/control macros that were
not defined in llvm-libc. This caused the fenv build to fail with a size mismatch in
fenv_darwin_impl.h and multiple undeclared-identifier errors for FE_FLUSHTOZERO and the
FPCR trap/flush bits.
The patch fixes that by updating the internal Darwin aarch64 floating-point state layout
to match fenv_t, defining the missing Darwin FPCR bit values used by the implementation,
and handling the flush-to-zero exception bit consistently.
This also fixes the Darwin sigsetjmp path by enabling sigjmp_buf support on Apple
targets, adding the Darwin signal pieces needed by that path (sigaddset, sigdelset,
sigemptyset, sigfillset, sigprocmask, plus signal macros), and updating the aarch64
sigsetjmp assembly to branch through a local label before jumping to setjmp, which avoids
an assembler error from using cbz with an external symbol target.
With these changes, ninja -C build libc libm now completes successfully locally.
---
Full diff: https://github.com/llvm/llvm-project/pull/192075.diff
13 Files Affected:
- (modified) libc/include/llvm-libc-macros/darwin/CMakeLists.txt (+6)
- (added) libc/include/llvm-libc-macros/darwin/signal-macros.h (+58)
- (modified) libc/include/llvm-libc-macros/signal-macros.h (+2)
- (modified) libc/include/llvm-libc-types/__jmp_buf.h (+1-1)
- (modified) libc/src/__support/FPUtil/aarch64/fenv_darwin_impl.h (+17-2)
- (modified) libc/src/setjmp/aarch64/sigsetjmp.cpp (+3-2)
- (modified) libc/src/setjmp/darwin/sigsetjmp_epilogue.cpp (+3-4)
- (added) libc/src/signal/darwin/CMakeLists.txt (+60)
- (added) libc/src/signal/darwin/sigaddset.cpp (+28)
- (added) libc/src/signal/darwin/sigdelset.cpp (+28)
- (added) libc/src/signal/darwin/sigemptyset.cpp (+28)
- (added) libc/src/signal/darwin/sigfillset.cpp (+29)
- (added) libc/src/signal/darwin/sigprocmask.cpp (+36)
``````````diff
diff --git a/libc/include/llvm-libc-macros/darwin/CMakeLists.txt b/libc/include/llvm-libc-macros/darwin/CMakeLists.txt
index ea08c63c00301..f3ee6af21d218 100644
--- a/libc/include/llvm-libc-macros/darwin/CMakeLists.txt
+++ b/libc/include/llvm-libc-macros/darwin/CMakeLists.txt
@@ -3,3 +3,9 @@ add_header(
HDR
time-macros.h
)
+
+add_header(
+ signal_macros
+ HDR
+ signal-macros.h
+)
diff --git a/libc/include/llvm-libc-macros/darwin/signal-macros.h b/libc/include/llvm-libc-macros/darwin/signal-macros.h
new file mode 100644
index 0000000000000..4bfaf79afdec6
--- /dev/null
+++ b/libc/include/llvm-libc-macros/darwin/signal-macros.h
@@ -0,0 +1,58 @@
+//===-- Definition of Darwin signal number macros -------------------------===//
+//
+// 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_MACROS_DARWIN_SIGNAL_MACROS_H
+#define LLVM_LIBC_MACROS_DARWIN_SIGNAL_MACROS_H
+
+#define SIGHUP 1
+#define SIGINT 2
+#define SIGQUIT 3
+#define SIGILL 4
+#define SIGTRAP 5
+#define SIGABRT 6
+#define SIGIOT 6
+#define SIGEMT 7
+#define SIGFPE 8
+#define SIGKILL 9
+#define SIGBUS 10
+#define SIGSEGV 11
+#define SIGSYS 12
+#define SIGPIPE 13
+#define SIGALRM 14
+#define SIGTERM 15
+#define SIGURG 16
+#define SIGSTOP 17
+#define SIGTSTP 18
+#define SIGCONT 19
+#define SIGCHLD 20
+#define SIGTTIN 21
+#define SIGTTOU 22
+#define SIGIO 23
+#define SIGXCPU 24
+#define SIGXFSZ 25
+#define SIGVTALRM 26
+#define SIGPROF 27
+#define SIGWINCH 28
+#define SIGINFO 29
+#define SIGUSR1 30
+#define SIGUSR2 31
+
+#define NSIG 32
+
+#define __NSIGSET_WORDS 1
+
+#define SIG_BLOCK 1
+#define SIG_UNBLOCK 2
+#define SIG_SETMASK 3
+
+#define SIG_ERR ((void (*)(int))-1)
+#define SIG_DFL ((void (*)(int))0)
+#define SIG_IGN ((void (*)(int))1)
+#define SIG_HOLD ((void (*)(int))5)
+
+#endif // LLVM_LIBC_MACROS_DARWIN_SIGNAL_MACROS_H
diff --git a/libc/include/llvm-libc-macros/signal-macros.h b/libc/include/llvm-libc-macros/signal-macros.h
index 163c8742593b8..c28f668456f33 100644
--- a/libc/include/llvm-libc-macros/signal-macros.h
+++ b/libc/include/llvm-libc-macros/signal-macros.h
@@ -11,6 +11,8 @@
#if defined(__linux__)
#include "linux/signal-macros.h"
+#elif defined(__APPLE__)
+#include "darwin/signal-macros.h"
#elif defined(__NVPTX__) || defined(__AMDGPU__) || defined(__SPIRV__)
#include "gpu/signal-macros.h"
#endif
diff --git a/libc/include/llvm-libc-types/__jmp_buf.h b/libc/include/llvm-libc-types/__jmp_buf.h
index a80afa2e6b815..266d2ffffa8b4 100644
--- a/libc/include/llvm-libc-types/__jmp_buf.h
+++ b/libc/include/llvm-libc-types/__jmp_buf.h
@@ -11,7 +11,7 @@
// TODO: implement sigjmp_buf related functions for other architectures
// Issue: https://github.com/llvm/llvm-project/issues/136358
-#if defined(__linux__)
+#if defined(__linux__) || defined(__APPLE__)
#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || \
defined(__arm__) || defined(__riscv)
#define __LIBC_HAS_SIGJMP_BUF
diff --git a/libc/src/__support/FPUtil/aarch64/fenv_darwin_impl.h b/libc/src/__support/FPUtil/aarch64/fenv_darwin_impl.h
index a2066d1025f63..3a541772f5dbb 100644
--- a/libc/src/__support/FPUtil/aarch64/fenv_darwin_impl.h
+++ b/libc/src/__support/FPUtil/aarch64/fenv_darwin_impl.h
@@ -29,14 +29,29 @@ namespace fputil {
struct FEnv {
struct FPState {
- uint64_t StatusWord;
- uint64_t ControlWord;
+ uint32_t ControlWord;
+ uint32_t StatusWord;
};
static_assert(
sizeof(fenv_t) == sizeof(FPState),
"Internal floating point state does not match the public fenv_t type.");
+#ifndef FE_FLUSHTOZERO
+#ifdef FE_DENORM
+ static constexpr uint32_t FE_FLUSHTOZERO = FE_DENORM;
+#else
+ static constexpr uint32_t FE_FLUSHTOZERO = 0;
+#endif
+#endif
+
+ static constexpr uint32_t __fpcr_trap_invalid = 0x100;
+ static constexpr uint32_t __fpcr_trap_overflow = 0x200;
+ static constexpr uint32_t __fpcr_trap_underflow = 0x400;
+ static constexpr uint32_t __fpcr_trap_divbyzero = 0x800;
+ static constexpr uint32_t __fpcr_trap_inexact = 0x1000;
+ static constexpr uint32_t __fpcr_flush_to_zero = 0x1000000;
+
static constexpr uint32_t TONEAREST = 0x0;
static constexpr uint32_t UPWARD = 0x1;
static constexpr uint32_t DOWNWARD = 0x2;
diff --git a/libc/src/setjmp/aarch64/sigsetjmp.cpp b/libc/src/setjmp/aarch64/sigsetjmp.cpp
index 734591b2aca4c..9be4f13db021c 100644
--- a/libc/src/setjmp/aarch64/sigsetjmp.cpp
+++ b/libc/src/setjmp/aarch64/sigsetjmp.cpp
@@ -17,8 +17,9 @@ namespace LIBC_NAMESPACE_DECL {
[[gnu::naked]]
LLVM_LIBC_FUNCTION(int, sigsetjmp, (sigjmp_buf, int)) {
asm(R"(
- cbz w1, %c[setjmp]
-
+ cbnz w1, 1f
+ b %c[setjmp]
+1:
str x30, [x0, %c[retaddr]]
str x19, [x0, %c[extra]]
mov x19, x0
diff --git a/libc/src/setjmp/darwin/sigsetjmp_epilogue.cpp b/libc/src/setjmp/darwin/sigsetjmp_epilogue.cpp
index 568545a20c50c..57165cbedb12b 100644
--- a/libc/src/setjmp/darwin/sigsetjmp_epilogue.cpp
+++ b/libc/src/setjmp/darwin/sigsetjmp_epilogue.cpp
@@ -7,15 +7,14 @@
//===----------------------------------------------------------------------===//
#include "src/setjmp/sigsetjmp_epilogue.h"
-#include "src/__support/OSUtil/syscall.h"
#include "src/__support/common.h"
#include "src/signal/sigprocmask.h"
namespace LIBC_NAMESPACE_DECL {
[[gnu::returns_twice]] int sigsetjmp_epilogue(sigjmp_buf buffer, int retval) {
- syscall_impl<long>(sigprocmask, SIG_SETMASK,
- /* set= */ retval ? &buffer->sigmask : nullptr,
- /* old_set= */ retval ? nullptr : &buffer->sigmask);
+ sigprocmask(SIG_SETMASK,
+ /* set= */ retval ? &buffer->sigmask : nullptr,
+ /* old_set= */ retval ? nullptr : &buffer->sigmask);
return retval;
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/signal/darwin/CMakeLists.txt b/libc/src/signal/darwin/CMakeLists.txt
new file mode 100644
index 0000000000000..c9621e0aa4418
--- /dev/null
+++ b/libc/src/signal/darwin/CMakeLists.txt
@@ -0,0 +1,60 @@
+add_entrypoint_object(
+ sigprocmask
+ SRCS
+ sigprocmask.cpp
+ HDRS
+ ../sigprocmask.h
+ DEPENDS
+ libc.src.__support.OSUtil.osutil
+ libc.src.__support.common
+ libc.src.__support.libc_errno
+ libc.src.__support.macros.config
+)
+
+add_entrypoint_object(
+ sigemptyset
+ SRCS
+ sigemptyset.cpp
+ HDRS
+ ../sigemptyset.h
+ DEPENDS
+ libc.src.__support.common
+ libc.src.__support.libc_errno
+ libc.src.__support.macros.config
+)
+
+add_entrypoint_object(
+ sigfillset
+ SRCS
+ sigfillset.cpp
+ HDRS
+ ../sigfillset.h
+ DEPENDS
+ libc.src.__support.common
+ libc.src.__support.libc_errno
+ libc.src.__support.macros.config
+)
+
+add_entrypoint_object(
+ sigaddset
+ SRCS
+ sigaddset.cpp
+ HDRS
+ ../sigaddset.h
+ DEPENDS
+ libc.src.__support.common
+ libc.src.__support.libc_errno
+ libc.src.__support.macros.config
+)
+
+add_entrypoint_object(
+ sigdelset
+ SRCS
+ sigdelset.cpp
+ HDRS
+ ../sigdelset.h
+ DEPENDS
+ libc.src.__support.common
+ libc.src.__support.libc_errno
+ libc.src.__support.macros.config
+)
diff --git a/libc/src/signal/darwin/sigaddset.cpp b/libc/src/signal/darwin/sigaddset.cpp
new file mode 100644
index 0000000000000..51f0cb8e4fc37
--- /dev/null
+++ b/libc/src/signal/darwin/sigaddset.cpp
@@ -0,0 +1,28 @@
+//===-- Darwin implementation of sigaddset ---------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#undef LIBC_COPT_PUBLIC_PACKAGING
+
+#include "src/signal/sigaddset.h"
+#include "hdr/types/sigset_t.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, sigaddset, (sigset_t * set, int signum)) {
+ if (!set || signum <= 0 || signum > 32) {
+ libc_errno = EINVAL;
+ return -1;
+ }
+ set->__signals[0] |= (1U << (signum - 1));
+ return 0;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/signal/darwin/sigdelset.cpp b/libc/src/signal/darwin/sigdelset.cpp
new file mode 100644
index 0000000000000..3bd767a16a508
--- /dev/null
+++ b/libc/src/signal/darwin/sigdelset.cpp
@@ -0,0 +1,28 @@
+//===-- Darwin implementation of sigdelset ---------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#undef LIBC_COPT_PUBLIC_PACKAGING
+
+#include "src/signal/sigdelset.h"
+#include "hdr/types/sigset_t.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, sigdelset, (sigset_t * set, int signum)) {
+ if (!set || signum <= 0 || signum > 32) {
+ libc_errno = EINVAL;
+ return -1;
+ }
+ set->__signals[0] &= ~(1U << (signum - 1));
+ return 0;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/signal/darwin/sigemptyset.cpp b/libc/src/signal/darwin/sigemptyset.cpp
new file mode 100644
index 0000000000000..aa04c54eca2fc
--- /dev/null
+++ b/libc/src/signal/darwin/sigemptyset.cpp
@@ -0,0 +1,28 @@
+//===-- Darwin implementation of sigemptyset -------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#undef LIBC_COPT_PUBLIC_PACKAGING
+
+#include "src/signal/sigemptyset.h"
+#include "hdr/types/sigset_t.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, sigemptyset, (sigset_t * set)) {
+ if (!set) {
+ libc_errno = EINVAL;
+ return -1;
+ }
+ set->__signals[0] = 0;
+ return 0;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/signal/darwin/sigfillset.cpp b/libc/src/signal/darwin/sigfillset.cpp
new file mode 100644
index 0000000000000..5a13885287013
--- /dev/null
+++ b/libc/src/signal/darwin/sigfillset.cpp
@@ -0,0 +1,29 @@
+//===-- Darwin implementation of sigfillset --------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#undef LIBC_COPT_PUBLIC_PACKAGING
+
+#include "src/signal/sigfillset.h"
+#include "hdr/types/sigset_t.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, sigfillset, (sigset_t * set)) {
+ if (!set) {
+ libc_errno = EINVAL;
+ return -1;
+ }
+ // Darwin sigset_t is 32-bit.
+ set->__signals[0] = 0xFFFFFFFFU;
+ return 0;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/signal/darwin/sigprocmask.cpp b/libc/src/signal/darwin/sigprocmask.cpp
new file mode 100644
index 0000000000000..d2296b0fd6da1
--- /dev/null
+++ b/libc/src/signal/darwin/sigprocmask.cpp
@@ -0,0 +1,36 @@
+//===-- Darwin implementation of sigprocmask -------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#undef LIBC_COPT_PUBLIC_PACKAGING
+
+#include "src/signal/sigprocmask.h"
+
+#include "hdr/types/sigset_t.h"
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, sigprocmask,
+ (int how, const sigset_t *__restrict set,
+ sigset_t *__restrict oldset)) {
+ // Darwin sigprocmask syscall uses 32-bit sigset_t. Since llvm-libc
+ // sigset_t is at least 64-bit on AArch64, passing its address is safe.
+ int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_sigprocmask, how, set, oldset);
+ if (ret >= 0)
+ return 0;
+
+ libc_errno = -ret;
+ return -1;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
``````````
</details>
https://github.com/llvm/llvm-project/pull/192075
More information about the libc-commits
mailing list