[libc-commits] [libc] [libc] Fix Darwin aarch64 fenv and sigsetjmp build support (PR #192079)
Kacper Fiedorowicz via libc-commits
libc-commits at lists.llvm.org
Tue Apr 14 08:53:42 PDT 2026
https://github.com/fenze created https://github.com/llvm/llvm-project/pull/192079
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 bits that were not defined in llvm-libc. This caused libc builds to fail in fenv_darwin_impl.h with a sizeof(fenv_t) vs. internal-state mismatch and multiple undeclared-identifier errors for FE_FLUSHTOZERO and the FPCR trap/flush bits.
This 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.
The patch 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 Darwin signal macros), and updating the aarch64 sigsetjmp inline assembly to branch through a local label before jumping to setjmp, avoiding an assembler error from using cbz with an external symbol target.
>From ace42c8b4f599cabbed8e79751d04ef08dc06c0d Mon Sep 17 00:00:00 2001
From: Kacper Fiedorowicz <kf at efab.pl>
Date: Tue, 14 Apr 2026 17:08:39 +0200
Subject: [PATCH] libc: fix Darwin signal and setjmp build support
---
.../llvm-libc-macros/darwin/CMakeLists.txt | 6 ++
.../llvm-libc-macros/darwin/signal-macros.h | 60 ++++++++++++++++
libc/include/llvm-libc-macros/signal-macros.h | 2 +
libc/include/llvm-libc-types/__jmp_buf.h | 2 +-
.../FPUtil/aarch64/fenv_darwin_impl.h | 19 ++++-
libc/src/setjmp/aarch64/sigsetjmp.cpp | 5 +-
libc/src/setjmp/darwin/sigsetjmp_epilogue.cpp | 7 +-
libc/src/signal/darwin/CMakeLists.txt | 70 +++++++++++++++++++
libc/src/signal/darwin/sigaddset.cpp | 26 +++++++
libc/src/signal/darwin/sigdelset.cpp | 26 +++++++
libc/src/signal/darwin/sigemptyset.cpp | 26 +++++++
libc/src/signal/darwin/sigfillset.cpp | 28 ++++++++
libc/src/signal/darwin/sigprocmask.cpp | 45 ++++++++++++
13 files changed, 313 insertions(+), 9 deletions(-)
create mode 100644 libc/include/llvm-libc-macros/darwin/signal-macros.h
create mode 100644 libc/src/signal/darwin/CMakeLists.txt
create mode 100644 libc/src/signal/darwin/sigaddset.cpp
create mode 100644 libc/src/signal/darwin/sigdelset.cpp
create mode 100644 libc/src/signal/darwin/sigemptyset.cpp
create mode 100644 libc/src/signal/darwin/sigfillset.cpp
create mode 100644 libc/src/signal/darwin/sigprocmask.cpp
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..88bfcc3db627c
--- /dev/null
+++ b/libc/include/llvm-libc-macros/darwin/signal-macros.h
@@ -0,0 +1,60 @@
+//===-- 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
+
+#include "__llvm-libc-common.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 __LLVM_LIBC_CAST(reinterpret_cast, void (*)(int), -1)
+#define SIG_DFL __LLVM_LIBC_CAST(reinterpret_cast, void (*)(int), 0)
+#define SIG_IGN __LLVM_LIBC_CAST(reinterpret_cast, void (*)(int), 1)
+#define SIG_HOLD __LLVM_LIBC_CAST(reinterpret_cast, 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..9d7661d60bb2e
--- /dev/null
+++ b/libc/src/signal/darwin/CMakeLists.txt
@@ -0,0 +1,70 @@
+add_entrypoint_object(
+ sigprocmask
+ SRCS
+ sigprocmask.cpp
+ HDRS
+ ../sigprocmask.h
+ DEPENDS
+ libc.hdr.types.sigset_t
+ libc.src.__support.OSUtil.osutil
+ libc.src.__support.common
+ libc.src.__support.libc_errno
+ libc.src.__support.macros.config
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ sigemptyset
+ SRCS
+ sigemptyset.cpp
+ HDRS
+ ../sigemptyset.h
+ DEPENDS
+ libc.hdr.types.sigset_t
+ libc.src.__support.common
+ libc.src.__support.libc_errno
+ libc.src.__support.macros.config
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ sigfillset
+ SRCS
+ sigfillset.cpp
+ HDRS
+ ../sigfillset.h
+ DEPENDS
+ libc.hdr.types.sigset_t
+ libc.src.__support.common
+ libc.src.__support.libc_errno
+ libc.src.__support.macros.config
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ sigaddset
+ SRCS
+ sigaddset.cpp
+ HDRS
+ ../sigaddset.h
+ DEPENDS
+ libc.hdr.types.sigset_t
+ libc.src.__support.common
+ libc.src.__support.libc_errno
+ libc.src.__support.macros.config
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ sigdelset
+ SRCS
+ sigdelset.cpp
+ HDRS
+ ../sigdelset.h
+ DEPENDS
+ libc.hdr.types.sigset_t
+ libc.src.__support.common
+ libc.src.__support.libc_errno
+ libc.src.__support.macros.config
+ libc.src.errno.errno
+)
diff --git a/libc/src/signal/darwin/sigaddset.cpp b/libc/src/signal/darwin/sigaddset.cpp
new file mode 100644
index 0000000000000..2f005adc75df3
--- /dev/null
+++ b/libc/src/signal/darwin/sigaddset.cpp
@@ -0,0 +1,26 @@
+//===-- 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
+//
+//===----------------------------------------------------------------------===//
+
+#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 >= NSIG) {
+ 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..d0d4f40cb98c3
--- /dev/null
+++ b/libc/src/signal/darwin/sigdelset.cpp
@@ -0,0 +1,26 @@
+//===-- 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
+//
+//===----------------------------------------------------------------------===//
+
+#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 >= NSIG) {
+ 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..bbb1a681d960c
--- /dev/null
+++ b/libc/src/signal/darwin/sigemptyset.cpp
@@ -0,0 +1,26 @@
+//===-- 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
+//
+//===----------------------------------------------------------------------===//
+
+#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..42a6aad9b9d4a
--- /dev/null
+++ b/libc/src/signal/darwin/sigfillset.cpp
@@ -0,0 +1,28 @@
+//===-- 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
+//
+//===----------------------------------------------------------------------===//
+
+#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;
+ }
+ // On Darwin, the supported signal mask here covers signals 1..31, so only
+ // the lower 32 bits of the first word are used and bit 31 remains clear.
+ set->__signals[0] = 0x7FFFFFFFU;
+ 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..37b9b155fa8e2
--- /dev/null
+++ b/libc/src/signal/darwin/sigprocmask.cpp
@@ -0,0 +1,45 @@
+//===-- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/signal/sigprocmask.h"
+
+#include "hdr/stdint_proxy.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)) {
+ uint32_t kernel_set = 0;
+ uint32_t kernel_oldset = 0;
+
+ if (set)
+ kernel_set = static_cast<uint32_t>(set->__signals[0] & 0x7FFFFFFFU);
+
+ int ret = LIBC_NAMESPACE::syscall_impl<int>(
+ SYS_sigprocmask, how, set ? &kernel_set : nullptr,
+ oldset ? &kernel_oldset : nullptr);
+ if (ret >= 0) {
+ if (oldset)
+ oldset->__signals[0] =
+ static_cast<unsigned long>(kernel_oldset & 0x7FFFFFFFU);
+ return 0;
+ }
+
+ libc_errno = -ret;
+ return -1;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
More information about the libc-commits
mailing list