[libc-commits] [libc] [libc] Implement ucontext functions for x86_64 (PR #187712)
Jeff Bailey via libc-commits
libc-commits at lists.llvm.org
Tue Apr 14 07:43:34 PDT 2026
https://github.com/kaladron updated https://github.com/llvm/llvm-project/pull/187712
>From 4e873e3c28cc7df8355bb1bb37cd48439cbf7dd8 Mon Sep 17 00:00:00 2001
From: Jeff Bailey <jbailey at raspberryginger.com>
Date: Fri, 20 Mar 2026 14:11:51 +0000
Subject: [PATCH 1/2] [libc] Implement x86_64 ucontext functions (#187712)
Implemented the x86_64 ucontext functions: getcontext, setcontext,
makecontext, and swapcontext.
The structures in mcontext_t.h and ucontext_t.h are defined to match the
system ABI specified in the Linux kernel headers and glibc, ensuring that
ucontext_t can correctly interpret contexts provided by the kernel in
signal handlers.
---
libc/config/linux/x86_64/entrypoints.txt | 6 +
libc/include/ucontext.h.def | 1 +
libc/src/CMakeLists.txt | 1 +
libc/src/ucontext/CMakeLists.txt | 31 +++++
libc/src/ucontext/getcontext.h | 22 +++
libc/src/ucontext/makecontext.h | 22 +++
libc/src/ucontext/setcontext.h | 22 +++
libc/src/ucontext/swapcontext.h | 22 +++
libc/src/ucontext/x86_64/CMakeLists.txt | 69 ++++++++++
libc/src/ucontext/x86_64/getcontext.cpp | 118 ++++++++++++++++
libc/src/ucontext/x86_64/makecontext.cpp | 94 +++++++++++++
libc/src/ucontext/x86_64/setcontext.cpp | 103 ++++++++++++++
libc/src/ucontext/x86_64/swapcontext.cpp | 144 ++++++++++++++++++++
libc/test/src/CMakeLists.txt | 1 +
libc/test/src/ucontext/CMakeLists.txt | 19 +++
libc/test/src/ucontext/ucontext_test.cpp | 166 +++++++++++++++++++++++
16 files changed, 841 insertions(+)
create mode 100644 libc/src/ucontext/CMakeLists.txt
create mode 100644 libc/src/ucontext/getcontext.h
create mode 100644 libc/src/ucontext/makecontext.h
create mode 100644 libc/src/ucontext/setcontext.h
create mode 100644 libc/src/ucontext/swapcontext.h
create mode 100644 libc/src/ucontext/x86_64/CMakeLists.txt
create mode 100644 libc/src/ucontext/x86_64/getcontext.cpp
create mode 100644 libc/src/ucontext/x86_64/makecontext.cpp
create mode 100644 libc/src/ucontext/x86_64/setcontext.cpp
create mode 100644 libc/src/ucontext/x86_64/swapcontext.cpp
create mode 100644 libc/test/src/ucontext/CMakeLists.txt
create mode 100644 libc/test/src/ucontext/ucontext_test.cpp
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 9476ebbad1517..df04a4d2be8de 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1251,6 +1251,12 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.setjmp.siglongjmp
libc.src.setjmp.sigsetjmp
+ # ucontext.h entrypoints
+ libc.src.ucontext.getcontext
+ libc.src.ucontext.setcontext
+ libc.src.ucontext.makecontext
+ libc.src.ucontext.swapcontext
+
# stdio.h entrypoints
libc.src.stdio.clearerr
libc.src.stdio.clearerr_unlocked
diff --git a/libc/include/ucontext.h.def b/libc/include/ucontext.h.def
index 0750d99a4a0c5..9b0581eb6ce00 100644
--- a/libc/include/ucontext.h.def
+++ b/libc/include/ucontext.h.def
@@ -11,6 +11,7 @@
#include "__llvm-libc-common.h"
+
%%public_api()
#endif // LLVM_LIBC_UCONTEXT_H
diff --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt
index e4b0de3d5c75d..ae5b2e53e11c8 100644
--- a/libc/src/CMakeLists.txt
+++ b/libc/src/CMakeLists.txt
@@ -45,6 +45,7 @@ add_subdirectory(locale)
add_subdirectory(nl_types)
add_subdirectory(search)
add_subdirectory(setjmp)
+add_subdirectory(ucontext)
add_subdirectory(signal)
add_subdirectory(spawn)
add_subdirectory(threads)
diff --git a/libc/src/ucontext/CMakeLists.txt b/libc/src/ucontext/CMakeLists.txt
new file mode 100644
index 0000000000000..67201bad898f5
--- /dev/null
+++ b/libc/src/ucontext/CMakeLists.txt
@@ -0,0 +1,31 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_ARCHITECTURE})
+ add_subdirectory(${LIBC_TARGET_ARCHITECTURE})
+endif()
+
+add_entrypoint_object(
+ getcontext
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_ARCHITECTURE}.getcontext
+)
+
+add_entrypoint_object(
+ setcontext
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_ARCHITECTURE}.setcontext
+)
+
+add_entrypoint_object(
+ makecontext
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_ARCHITECTURE}.makecontext
+)
+
+add_entrypoint_object(
+ swapcontext
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_ARCHITECTURE}.swapcontext
+)
diff --git a/libc/src/ucontext/getcontext.h b/libc/src/ucontext/getcontext.h
new file mode 100644
index 0000000000000..804feed18f539
--- /dev/null
+++ b/libc/src/ucontext/getcontext.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for getcontext ----------------------*- 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_UCONTEXT_GETCONTEXT_H
+#define LLVM_LIBC_SRC_UCONTEXT_GETCONTEXT_H
+
+#include "include/llvm-libc-types/ucontext_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int getcontext(ucontext_t *ucp);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_UCONTEXT_GETCONTEXT_H
diff --git a/libc/src/ucontext/makecontext.h b/libc/src/ucontext/makecontext.h
new file mode 100644
index 0000000000000..ebf4e48b8d7d9
--- /dev/null
+++ b/libc/src/ucontext/makecontext.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for makecontext ---------------------*- 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_UCONTEXT_MAKECONTEXT_H
+#define LLVM_LIBC_SRC_UCONTEXT_MAKECONTEXT_H
+
+#include "include/llvm-libc-types/ucontext_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+void makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_UCONTEXT_MAKECONTEXT_H
diff --git a/libc/src/ucontext/setcontext.h b/libc/src/ucontext/setcontext.h
new file mode 100644
index 0000000000000..c42feb1fe24f3
--- /dev/null
+++ b/libc/src/ucontext/setcontext.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for setcontext ----------------------*- 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_UCONTEXT_SETCONTEXT_H
+#define LLVM_LIBC_SRC_UCONTEXT_SETCONTEXT_H
+
+#include "include/llvm-libc-types/ucontext_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int setcontext(const ucontext_t *ucp);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_UCONTEXT_SETCONTEXT_H
diff --git a/libc/src/ucontext/swapcontext.h b/libc/src/ucontext/swapcontext.h
new file mode 100644
index 0000000000000..c35490aed6ffc
--- /dev/null
+++ b/libc/src/ucontext/swapcontext.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for swapcontext ---------------------*- 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_UCONTEXT_SWAPCONTEXT_H
+#define LLVM_LIBC_SRC_UCONTEXT_SWAPCONTEXT_H
+
+#include "include/llvm-libc-types/ucontext_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int swapcontext(ucontext_t *__restrict oucp, const ucontext_t *__restrict ucp);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_UCONTEXT_SWAPCONTEXT_H
diff --git a/libc/src/ucontext/x86_64/CMakeLists.txt b/libc/src/ucontext/x86_64/CMakeLists.txt
new file mode 100644
index 0000000000000..ef26ca5e1e1c6
--- /dev/null
+++ b/libc/src/ucontext/x86_64/CMakeLists.txt
@@ -0,0 +1,69 @@
+add_entrypoint_object(
+ getcontext
+ SRCS
+ getcontext.cpp
+ HDRS
+ ../getcontext.h
+ COMPILE_OPTIONS
+ -O3
+ -fno-omit-frame-pointer
+ DEPENDS
+ libc.include.llvm-libc-types.ucontext_t
+ libc.include.sys_syscall
+ libc.src.__support.common
+ libc.src.__support.macros.config
+ libc.hdr.types.size_t
+)
+
+add_entrypoint_object(
+ setcontext
+ SRCS
+ setcontext.cpp
+ HDRS
+ ../setcontext.h
+ COMPILE_OPTIONS
+ -O3
+ -fno-omit-frame-pointer
+ DEPENDS
+ libc.include.llvm-libc-types.ucontext_t
+ libc.include.sys_syscall
+ libc.src.__support.common
+ libc.src.__support.macros.config
+ libc.hdr.types.size_t
+)
+
+add_entrypoint_object(
+ makecontext
+ SRCS
+ makecontext.cpp
+ HDRS
+ ../makecontext.h
+ COMPILE_OPTIONS
+ -O3
+ -fno-omit-frame-pointer
+ DEPENDS
+ libc.include.llvm-libc-types.ucontext_t
+ libc.src.__support.common
+ libc.src.__support.macros.config
+ libc.src.__support.OSUtil.osutil
+ .setcontext
+ libc.hdr.types.size_t
+ libc.hdr.stdint_proxy
+)
+
+add_entrypoint_object(
+ swapcontext
+ SRCS
+ swapcontext.cpp
+ HDRS
+ ../swapcontext.h
+ COMPILE_OPTIONS
+ -O3
+ -fno-omit-frame-pointer
+ DEPENDS
+ libc.include.llvm-libc-types.ucontext_t
+ libc.include.sys_syscall
+ libc.src.__support.common
+ libc.src.__support.macros.config
+ libc.hdr.types.size_t
+)
diff --git a/libc/src/ucontext/x86_64/getcontext.cpp b/libc/src/ucontext/x86_64/getcontext.cpp
new file mode 100644
index 0000000000000..082599bb6017a
--- /dev/null
+++ b/libc/src/ucontext/x86_64/getcontext.cpp
@@ -0,0 +1,118 @@
+//===-- Implementation of getcontext for x86_64 ---------------------------===//
+//
+// 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/ucontext/getcontext.h"
+#include "include/llvm-libc-types/ucontext_t.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+#include "hdr/types/size_t.h"
+#include <sys/syscall.h>
+
+// We define these locally so we don't depend on system headers.
+// These are the standard sysV x86_64 ABI indices for gregset_t.
+
+namespace LIBC_NAMESPACE_DECL {
+
+// We use naked because we need to capture the exact register state
+// at the moment of the function call, avoiding any compiler prologue/epilogue.
+[[gnu::naked]]
+LLVM_LIBC_FUNCTION(int, getcontext, (ucontext_t * ucp)) {
+ asm(R"(
+ # ucp is in rdi
+
+ # Save general purpose registers
+ mov %%r8, %c[r8](%%rdi)
+ mov %%r9, %c[r9](%%rdi)
+ mov %%r10, %c[r10](%%rdi)
+ mov %%r11, %c[r11](%%rdi)
+ mov %%r12, %c[r12](%%rdi)
+ mov %%r13, %c[r13](%%rdi)
+ mov %%r14, %c[r14](%%rdi)
+ mov %%r15, %c[r15](%%rdi)
+ mov %%rdi, %c[rdi](%%rdi)
+ mov %%rsi, %c[rsi](%%rdi)
+ mov %%rbp, %c[rbp](%%rdi)
+ mov %%rbx, %c[rbx](%%rdi)
+ mov %%rdx, %c[rdx](%%rdi)
+ # getcontext should return 0 when resumed by setcontext.
+ # So we save 0 into the RAX register of the context.
+ movq $0, %c[rax](%%rdi)
+ mov %%rcx, %c[rcx](%%rdi)
+
+ # The stack pointer before the call is rsp + sizeof(void*).
+ # The return address was pushed when this function was called.
+ # Save instruction pointer and stack pointer
+ mov (%%rsp), %%rax
+ mov %%rax, %c[rip](%%rdi)
+ lea %c[ret_size](%%rsp), %%rax
+ mov %%rax, %c[rsp](%%rdi)
+
+ # Save floating point state
+ fxsaveq %c[fpregs_mem](%%rdi)
+ # Point mcontext.fpregs to our internal FP storage
+ lea %c[fpregs_mem](%%rdi), %%rax
+ mov %%rax, %c[fpregs_ptr](%%rdi)
+
+ # Capture the signal mask using rt_sigprocmask syscall.
+ # rt_sigprocmask(SIG_BLOCK, NULL, &ucp->uc_sigmask, sizeof(sigset_t))
+ leaq %c[sigmask](%%rdi), %%rdx # oldset = &ucp->uc_sigmask
+ xorq %%rsi, %%rsi # set = NULL
+ movq $0, %%rdi # SIG_BLOCK (captured mask in oldset)
+ movq $%c[sigset_size], %%r10
+ movq $%c[syscall_num], %%rax
+ syscall
+
+ # getcontext should return 0 on success
+ xor %%eax, %%eax
+
+ retq
+ )" ::[ret_size] "i"(sizeof(void *)),
+ [sigset_size] "i"(sizeof(sigset_t)),
+ [syscall_num] "i"(SYS_rt_sigprocmask),
+ [r8] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R8])),
+ [r9] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R9])),
+ [r10] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R10])),
+ [r11] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R11])),
+ [r12] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R12])),
+ [r13] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R13])),
+ [r14] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R14])),
+ [r15] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R15])),
+ [rdi] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RDI])),
+ [rsi] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RSI])),
+ [rbp] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RBP])),
+ [rbx] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RBX])),
+ [rdx] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RDX])),
+ [rax] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RAX])),
+ [rcx] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RCX])),
+ [rsp] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RSP])),
+ [rip] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RIP])),
+ [fpregs_mem] "i"(__builtin_offsetof(ucontext_t, __fpregs_mem)),
+ [fpregs_ptr] "i"(__builtin_offsetof(ucontext_t, uc_mcontext.fpregs)),
+ [sigmask] "i"(__builtin_offsetof(ucontext_t, uc_sigmask))
+ : "memory", "rcx", "r11");
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/ucontext/x86_64/makecontext.cpp b/libc/src/ucontext/x86_64/makecontext.cpp
new file mode 100644
index 0000000000000..7a757d3f42251
--- /dev/null
+++ b/libc/src/ucontext/x86_64/makecontext.cpp
@@ -0,0 +1,94 @@
+//===-- Implementation of makecontext for x86_64 --------------------------===//
+//
+// 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/ucontext/makecontext.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+#include "hdr/stdint_proxy.h"
+#include "hdr/types/size_t.h"
+#include "include/llvm-libc-types/ucontext_t.h"
+#include <stdarg.h>
+
+#include "src/__support/OSUtil/exit.h"
+#include "src/ucontext/setcontext.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+extern "C" void __makecontext_trampoline_c(ucontext_t *uc_link) {
+ if (uc_link)
+ setcontext(uc_link);
+
+ internal::exit(0);
+}
+
+[[gnu::naked]] void __makecontext_trampoline() {
+ asm(R"(
+ mov %rbx, %rdi
+ call __makecontext_trampoline_c
+ hlt
+ )");
+}
+
+LLVM_LIBC_FUNCTION(void, makecontext,
+ (ucontext_t * ucp, void (*func)(void), int argc, ...)) {
+ if (!ucp || !func)
+ return;
+
+ // System V AMD64 ABI requirements.
+ constexpr uintptr_t STACK_ALIGN_BYTES = 16;
+ constexpr uintptr_t STACK_ALIGN_MASK = ~(STACK_ALIGN_BYTES - 1);
+ constexpr int REGISTER_ARGS_COUNT = 6;
+ constexpr uintptr_t ARG_SIZE = sizeof(greg_t);
+
+ uintptr_t stack_top =
+ reinterpret_cast<uintptr_t>(ucp->uc_stack.ss_sp) + ucp->uc_stack.ss_size;
+ stack_top &= STACK_ALIGN_MASK;
+
+ int stack_args = argc > REGISTER_ARGS_COUNT ? argc - REGISTER_ARGS_COUNT : 0;
+
+ uintptr_t new_rsp = stack_top - stack_args * ARG_SIZE;
+ new_rsp &= STACK_ALIGN_MASK;
+
+ // The System V ABI requires the stack to be 16-byte aligned before the 'call'
+ // instruction. When a function is entered, the return address has been
+ // pushed, making the stack misaligned by 8. We simulate this state by
+ // subtracting 8, storing the trampoline address at the top of the stack.
+ new_rsp -= ARG_SIZE;
+
+ greg_t *stack_area = reinterpret_cast<greg_t *>(new_rsp);
+ stack_area[0] = reinterpret_cast<greg_t>(&__makecontext_trampoline);
+
+ va_list ap;
+ va_start(ap, argc);
+ if (argc > 0)
+ ucp->uc_mcontext.gregs[__LIBC_REG_RDI] = va_arg(ap, greg_t);
+ if (argc > 1)
+ ucp->uc_mcontext.gregs[__LIBC_REG_RSI] = va_arg(ap, greg_t);
+ if (argc > 2)
+ ucp->uc_mcontext.gregs[__LIBC_REG_RDX] = va_arg(ap, greg_t);
+ if (argc > 3)
+ ucp->uc_mcontext.gregs[__LIBC_REG_RCX] = va_arg(ap, greg_t);
+ if (argc > 4)
+ ucp->uc_mcontext.gregs[__LIBC_REG_R8] = va_arg(ap, greg_t);
+ if (argc > 5)
+ ucp->uc_mcontext.gregs[__LIBC_REG_R9] = va_arg(ap, greg_t);
+
+ for (int i = 0; i < stack_args; ++i) {
+ stack_area[i + 1] = va_arg(ap, greg_t);
+ }
+
+ va_end(ap);
+
+ ucp->uc_mcontext.gregs[__LIBC_REG_RIP] = reinterpret_cast<greg_t>(func);
+ ucp->uc_mcontext.gregs[__LIBC_REG_RSP] = new_rsp;
+ ucp->uc_mcontext.gregs[__LIBC_REG_RBX] =
+ reinterpret_cast<greg_t>(ucp->uc_link);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/ucontext/x86_64/setcontext.cpp b/libc/src/ucontext/x86_64/setcontext.cpp
new file mode 100644
index 0000000000000..95ca78e239085
--- /dev/null
+++ b/libc/src/ucontext/x86_64/setcontext.cpp
@@ -0,0 +1,103 @@
+//===-- Implementation of setcontext for x86_64 ---------------------------===//
+//
+// 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/ucontext/setcontext.h"
+#include "include/llvm-libc-types/ucontext_t.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+#include "hdr/types/size_t.h"
+#include <sys/syscall.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+[[gnu::naked]]
+LLVM_LIBC_FUNCTION(int, setcontext, (const ucontext_t *ucp)) {
+ asm(R"(
+ # ucp is in rdi
+
+ # Restore the signal mask using rt_sigprocmask syscall.
+ # rt_sigprocmask(SIG_SETMASK, &ucp->uc_sigmask, NULL, sizeof(sigset_t))
+ pushq %%rdi # Save ucp
+ leaq %c[sigmask](%%rdi), %%rsi # set = &ucp->uc_sigmask
+ xorq %%rdx, %%rdx # oldset = NULL
+ movq $%c[sigset_size], %%r10 # sigsetsize = sizeof(sigset_t)
+ movq $2, %%rdi # how = SIG_SETMASK
+ movq $%c[syscall_num], %%rax
+ syscall
+ popq %%rdi # Restore ucp
+
+ # Restore floating point state
+ fxrstorq %c[fpregs_mem](%%rdi)
+
+ # Restore other general purpose registers
+ mov %c[r8](%%rdi), %%r8
+ mov %c[r9](%%rdi), %%r9
+ mov %c[r10](%%rdi), %%r10
+ mov %c[r11](%%rdi), %%r11
+ mov %c[r12](%%rdi), %%r12
+ mov %c[r13](%%rdi), %%r13
+ mov %c[r14](%%rdi), %%r14
+ mov %c[r15](%%rdi), %%r15
+ mov %c[rbp](%%rdi), %%rbp
+ mov %c[rbx](%%rdi), %%rbx
+ mov %c[rdx](%%rdi), %%rdx
+ mov %c[rax](%%rdi), %%rax
+ mov %c[rcx](%%rdi), %%rcx
+
+ # Restore stack pointer and instruction pointer
+ mov %c[rsp](%%rdi), %%rsp
+ mov %c[rip](%%rdi), %%r11 # Use r11 as temp for rip
+
+ # Restore RSI and RDI last
+ mov %c[rsi](%%rdi), %%rsi
+ mov %c[rdi](%%rdi), %%rdi
+
+ jmpq *%%r11 # Jump to the saved instruction pointer
+ )" ::[sigset_size] "i"(sizeof(sigset_t)),
+ [syscall_num] "i"(SYS_rt_sigprocmask),
+ [r8] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R8])),
+ [r9] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R9])),
+ [r10] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R10])),
+ [r11] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R11])),
+ [r12] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R12])),
+ [r13] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R13])),
+ [r14] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R14])),
+ [r15] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R15])),
+ [rdi] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RDI])),
+ [rsi] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RSI])),
+ [rbp] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RBP])),
+ [rbx] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RBX])),
+ [rdx] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RDX])),
+ [rax] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RAX])),
+ [rcx] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RCX])),
+ [rsp] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RSP])),
+ [rip] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RIP])),
+ [fpregs_mem] "i"(__builtin_offsetof(ucontext_t, __fpregs_mem)),
+ [sigmask] "i"(__builtin_offsetof(ucontext_t, uc_sigmask))
+ : "memory", "rcx", "r11");
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/ucontext/x86_64/swapcontext.cpp b/libc/src/ucontext/x86_64/swapcontext.cpp
new file mode 100644
index 0000000000000..7115e5c4059f1
--- /dev/null
+++ b/libc/src/ucontext/x86_64/swapcontext.cpp
@@ -0,0 +1,144 @@
+//===-- Implementation of swapcontext for x86_64 --------------------------===//
+//
+// 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/ucontext/swapcontext.h"
+#include "include/llvm-libc-types/ucontext_t.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+#include "hdr/types/size_t.h"
+#include <sys/syscall.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+[[gnu::naked]]
+LLVM_LIBC_FUNCTION(int, swapcontext,
+ (ucontext_t * oucp, const ucontext_t *ucp)) {
+ asm(R"(
+ # oucp is in rdi, ucp is in rsi
+
+ // Save current context into oucp
+ // Save general purpose registers
+ mov %%r8, %c[r8](%%rdi)
+ mov %%r9, %c[r9](%%rdi)
+ mov %%r10, %c[r10](%%rdi)
+ mov %%r11, %c[r11](%%rdi)
+ mov %%r12, %c[r12](%%rdi)
+ mov %%r13, %c[r13](%%rdi)
+ mov %%r14, %c[r14](%%rdi)
+ mov %%r15, %c[r15](%%rdi)
+ mov %%rdi, %c[rdi](%%rdi) # oucp itself
+ mov %%rsi, %c[rsi](%%rdi) # ucp
+ mov %%rbp, %c[rbp](%%rdi)
+ mov %%rbx, %c[rbx](%%rdi)
+ mov %%rdx, %c[rdx](%%rdi)
+ // setcontext should return 0 when resumed by setcontext.
+ // So we save 0 into the RAX register of the context.
+ movq $0, %c[rax](%%rdi)
+ mov %%rcx, %c[rcx](%%rdi)
+
+ // The stack pointer before the call is rsp + sizeof(void*).
+ // The return address was pushed when this function was called.
+ // Save instruction pointer and stack pointer
+ mov (%%rsp), %%rax
+ mov %%rax, %c[rip](%%rdi)
+ lea %c[ret_size](%%rsp), %%rax
+ mov %%rax, %c[rsp](%%rdi)
+
+ // Save floating point state
+ fxsaveq %c[fpregs_mem](%%rdi)
+ // Point mcontext.fpregs to our internal FP storage
+ lea %c[fpregs_mem](%%rdi), %%rax
+ mov %%rax, %c[fpregs_ptr](%%rdi)
+
+ // Capture oucp signal mask and restore ucp signal mask atomically.
+ // rt_sigprocmask(SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask, sizeof(sigset_t))
+ // oucp is in rdi, ucp is in rsi
+ pushq %%rdi # Save oucp
+ pushq %%rsi # Save ucp
+ leaq %c[sigmask](%%rdi), %%rdx # oldset = &oucp->uc_sigmask
+ leaq %c[sigmask](%%rsi), %%rsi # set = &ucp->uc_sigmask
+ movq $%c[sigset_size], %%r10 # sigsetsize = sizeof(sigset_t)
+ movq $2, %%rdi # how = SIG_SETMASK
+ movq $%c[syscall_num], %%rax
+ syscall
+ popq %%rsi # Restore ucp (new context)
+ popq %%rdi # Restore oucp (old context - not needed but for clean stack)
+
+ // Restore context from ucp (now in rsi)
+ // Restore floating point state
+ fxrstorq %c[fpregs_mem](%%rsi)
+
+ // Restore general purpose registers EXECPT rdi, rsi, rsp, rip
+ mov %c[r8](%%rsi), %%r8
+ mov %c[r9](%%rsi), %%r9
+ mov %c[r10](%%rsi), %%r10
+ mov %c[r11](%%rsi), %%r11
+ mov %c[r12](%%rsi), %%r12
+ mov %c[r13](%%rsi), %%r13
+ mov %c[r14](%%rsi), %%r14
+ mov %c[r15](%%rsi), %%r15
+ mov %c[rbp](%%rsi), %%rbp
+ mov %c[rbx](%%rsi), %%rbx
+ mov %c[rdx](%%rsi), %%rdx
+ mov %c[rax](%%rsi), %%rax
+ mov %c[rcx](%%rsi), %%rcx
+
+ // Restore stack pointer and instruction pointer
+ mov %c[rsp](%%rsi), %%rsp
+ mov %c[rip](%%rsi), %%r11 # Use r11 as temp for rip
+
+ // Restore RSI and RDI last
+ mov %c[rdi](%%rsi), %%rdi
+ mov %c[rsi](%%rsi), %%rsi
+
+ jmpq *%%r11 # Jump to the saved instruction pointer
+ )" ::[ret_size] "i"(sizeof(void *)),
+ [sigset_size] "i"(sizeof(sigset_t)),
+ [syscall_num] "i"(SYS_rt_sigprocmask),
+ [r8] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R8])),
+ [r9] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R9])),
+ [r10] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R10])),
+ [r11] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R11])),
+ [r12] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R12])),
+ [r13] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R13])),
+ [r14] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R14])),
+ [r15] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R15])),
+ [rdi] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RDI])),
+ [rsi] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RSI])),
+ [rbp] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RBP])),
+ [rbx] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RBX])),
+ [rdx] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RDX])),
+ [rax] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RAX])),
+ [rcx] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RCX])),
+ [rsp] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RSP])),
+ [rip] "i"(
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RIP])),
+ [fpregs_mem] "i"(__builtin_offsetof(ucontext_t, __fpregs_mem)),
+ [fpregs_ptr] "i"(__builtin_offsetof(ucontext_t, uc_mcontext.fpregs)),
+ [sigmask] "i"(__builtin_offsetof(ucontext_t, uc_sigmask))
+ : "memory", "rcx", "r11");
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/src/CMakeLists.txt b/libc/test/src/CMakeLists.txt
index 236bee337d525..ec1219f687797 100644
--- a/libc/test/src/CMakeLists.txt
+++ b/libc/test/src/CMakeLists.txt
@@ -65,6 +65,7 @@ add_subdirectory(fenv)
add_subdirectory(math)
add_subdirectory(search)
add_subdirectory(setjmp)
+add_subdirectory(ucontext)
add_subdirectory(stdbit)
add_subdirectory(stdfix)
add_subdirectory(stdio)
diff --git a/libc/test/src/ucontext/CMakeLists.txt b/libc/test/src/ucontext/CMakeLists.txt
new file mode 100644
index 0000000000000..8dae7050e1f86
--- /dev/null
+++ b/libc/test/src/ucontext/CMakeLists.txt
@@ -0,0 +1,19 @@
+add_custom_target(libc_ucontext_unittests)
+
+if(TARGET libc.src.ucontext.getcontext)
+ add_libc_unittest(
+ ucontext_test
+ SUITE
+ libc_ucontext_unittests
+ SRCS
+ ucontext_test.cpp
+ DEPENDS
+ libc.src.ucontext.getcontext
+ libc.src.ucontext.setcontext
+ libc.src.ucontext.makecontext
+ libc.src.ucontext.swapcontext
+ libc.src.signal.sigemptyset
+ libc.src.signal.sigaddset
+ libc.src.signal.sigprocmask
+ )
+endif()
diff --git a/libc/test/src/ucontext/ucontext_test.cpp b/libc/test/src/ucontext/ucontext_test.cpp
new file mode 100644
index 0000000000000..f94195e37057c
--- /dev/null
+++ b/libc/test/src/ucontext/ucontext_test.cpp
@@ -0,0 +1,166 @@
+//===-- Unittests for ucontext routines -----------------------------------===//
+//
+// 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/ucontext/getcontext.h"
+#include "src/ucontext/makecontext.h"
+#include "src/ucontext/setcontext.h"
+#include "src/ucontext/swapcontext.h"
+
+#include "src/signal/sigaddset.h"
+#include "src/signal/sigemptyset.h"
+#include "src/signal/sigprocmask.h"
+
+#include "test/UnitTest/Test.h"
+
+#include "include/llvm-libc-macros/signal-macros.h"
+
+namespace LIBC_NAMESPACE {
+
+static bool is_signal_set(const sigset_t *set, int signum) {
+ // NSIG is 64, sigset_t is an array of unsigned long.
+ // Signum is 1-indexed.
+ int word = (signum - 1) / (sizeof(unsigned long) * 8);
+ int bit = (signum - 1) % (sizeof(unsigned long) * 8);
+ return (set->__signals[word] & (1UL << bit)) != 0;
+}
+
+volatile int jumped = 0;
+TEST(LlvmLibcUcontextTest, BasicStubTest) {
+ ucontext_t ctx;
+ ASSERT_EQ(getcontext(&ctx), 0);
+ if (!jumped) {
+ jumped = 1;
+ setcontext(&ctx);
+ ASSERT_TRUE(false && "setcontext should not return on success");
+ }
+}
+
+ucontext_t old_ctx, new_ctx;
+volatile int swap_called = 0;
+
+void swap_func() {
+ swap_called = 1;
+ setcontext(&old_ctx);
+}
+
+TEST(LlvmLibcUcontextTest, SwapcontextTest) {
+ getcontext(&new_ctx);
+ constexpr size_t STACK_SIZE = 8192;
+ char stack[STACK_SIZE];
+ new_ctx.uc_stack.ss_sp = stack;
+ new_ctx.uc_stack.ss_size = sizeof(stack);
+ makecontext(&new_ctx, swap_func, 0);
+
+ swapcontext(&old_ctx, &new_ctx);
+
+ ASSERT_EQ(swap_called, 1);
+}
+
+ucontext_t old_ctx_args, new_ctx_args;
+volatile int makecontext_args_called = 0;
+volatile int arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
+
+void args_func(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) {
+ makecontext_args_called = 1;
+ arg1 = a1;
+ arg2 = a2;
+ arg3 = a3;
+ arg4 = a4;
+ arg5 = a5;
+ arg6 = a6;
+ arg7 = a7;
+ arg8 = a8;
+ setcontext(&old_ctx_args);
+}
+
+TEST(LlvmLibcUcontextTest, MakecontextArgsTest) {
+ getcontext(&new_ctx_args);
+ constexpr size_t STACK_SIZE = 8192;
+ char stack[STACK_SIZE];
+ new_ctx_args.uc_stack.ss_sp = stack;
+ new_ctx_args.uc_stack.ss_size = sizeof(stack);
+
+ // Cast function pointer to void(*)(void) as required by makecontext
+ using func_t = void (*)(void);
+ auto func = reinterpret_cast<func_t>(args_func);
+
+ makecontext(&new_ctx_args, func, 8, 11, 22, 33, 44, 55, 66, 77, 88);
+
+ swapcontext(&old_ctx_args, &new_ctx_args);
+
+ ASSERT_EQ(makecontext_args_called, 1);
+ ASSERT_EQ(arg1, 11);
+ ASSERT_EQ(arg2, 22);
+ ASSERT_EQ(arg3, 33);
+ ASSERT_EQ(arg4, 44);
+ ASSERT_EQ(arg5, 55);
+ ASSERT_EQ(arg6, 66);
+ ASSERT_EQ(arg8, 88);
+}
+
+ucontext_t old_ctx_return, new_ctx_return;
+volatile int makecontext_return_called = 0;
+
+void return_func() { makecontext_return_called = 1; }
+
+TEST(LlvmLibcUcontextTest, MakecontextReturnTest) {
+ getcontext(&new_ctx_return);
+ constexpr size_t STACK_SIZE = 8192;
+ char stack[STACK_SIZE];
+ new_ctx_return.uc_stack.ss_sp = stack;
+ new_ctx_return.uc_stack.ss_size = sizeof(stack);
+ new_ctx_return.uc_link = &old_ctx_return;
+
+ using func_t = void (*)(void);
+ auto func = reinterpret_cast<func_t>(return_func);
+
+ makecontext(&new_ctx_return, func, 0);
+
+ swapcontext(&old_ctx_return, &new_ctx_return);
+
+ ASSERT_EQ(makecontext_return_called, 1);
+}
+
+TEST(LlvmLibcUcontextTest, SignalMaskTest) {
+ sigset_t set, old_set;
+ sigemptyset(&set);
+ sigaddset(&set, SIGUSR1);
+
+ // Set mask to [SIGUSR1] using sigprocmask
+ sigprocmask(SIG_SETMASK, &set, &old_set);
+
+ ucontext_t ctx;
+ getcontext(&ctx);
+
+ // Verify that getcontext captured the mask
+ ASSERT_TRUE(is_signal_set(&ctx.uc_sigmask, SIGUSR1));
+ ASSERT_FALSE(is_signal_set(&ctx.uc_sigmask, SIGUSR2));
+
+ sigset_t new_set;
+ static volatile int mask_jumped = 0;
+ if (mask_jumped == 0) {
+ mask_jumped = 1;
+ sigemptyset(&new_set);
+ sigaddset(&new_set, SIGUSR2);
+ sigprocmask(SIG_SETMASK, &new_set, nullptr);
+
+ setcontext(&ctx);
+ }
+
+ // Check current mask
+ sigset_t current;
+ sigprocmask(SIG_BLOCK, nullptr, ¤t);
+
+ // Restore original mask for clean state
+ sigprocmask(SIG_SETMASK, &old_set, nullptr);
+
+ ASSERT_TRUE(is_signal_set(¤t, SIGUSR1));
+ ASSERT_FALSE(is_signal_set(¤t, SIGUSR2));
+}
+
+} // namespace LIBC_NAMESPACE
>From 2f1e3c432bfb535f702026663d7d219bfcd16e7a Mon Sep 17 00:00:00 2001
From: Jeff Bailey <jbailey at raspberryginger.com>
Date: Tue, 14 Apr 2026 14:42:12 +0100
Subject: [PATCH 2/2] [libc] Fix ucontext implementation after rebase
Updated x86_64 ucontext implementation to work with the rebased headers:
* Renamed __LIBC_REG_* constants to REG_* in all x86_64 implementation files.
* Fixed guard macros in x86_64/mcontext_t.h and x86_64/ucontext_t.h to avoid collision with parent headers.
---
.../llvm-libc-types/x86_64/mcontext_t.h | 6 ++--
.../llvm-libc-types/x86_64/ucontext_t.h | 6 ++--
libc/src/ucontext/x86_64/getcontext.cpp | 34 +++++++++----------
libc/src/ucontext/x86_64/makecontext.cpp | 18 +++++-----
libc/src/ucontext/x86_64/setcontext.cpp | 34 +++++++++----------
libc/src/ucontext/x86_64/swapcontext.cpp | 34 +++++++++----------
6 files changed, 66 insertions(+), 66 deletions(-)
diff --git a/libc/include/llvm-libc-types/x86_64/mcontext_t.h b/libc/include/llvm-libc-types/x86_64/mcontext_t.h
index df9263f9411eb..4351f491294e7 100644
--- a/libc/include/llvm-libc-types/x86_64/mcontext_t.h
+++ b/libc/include/llvm-libc-types/x86_64/mcontext_t.h
@@ -8,8 +8,8 @@
// Note: Definitions in this file are based on the Linux kernel ABI.
-#ifndef LLVM_LIBC_TYPES_MCONTEXT_T_H
-#define LLVM_LIBC_TYPES_MCONTEXT_T_H
+#ifndef LLVM_LIBC_TYPES_X86_64_MCONTEXT_T_H
+#define LLVM_LIBC_TYPES_X86_64_MCONTEXT_T_H
// The following definitions correspond to the general purpose registers.
// The layout of gregset_t and the enum indices must match the layout of
@@ -118,4 +118,4 @@ typedef struct {
unsigned long long __reserved1[8];
} mcontext_t;
-#endif // LLVM_LIBC_TYPES_MCONTEXT_T_H
+#endif // LLVM_LIBC_TYPES_X86_64_MCONTEXT_T_H
diff --git a/libc/include/llvm-libc-types/x86_64/ucontext_t.h b/libc/include/llvm-libc-types/x86_64/ucontext_t.h
index 607c2d1a6b2a0..15d755050076f 100644
--- a/libc/include/llvm-libc-types/x86_64/ucontext_t.h
+++ b/libc/include/llvm-libc-types/x86_64/ucontext_t.h
@@ -8,8 +8,8 @@
// Note: Definitions in this file are based on the Linux kernel ABI.
-#ifndef LLVM_LIBC_TYPES_UCONTEXT_T_H
-#define LLVM_LIBC_TYPES_UCONTEXT_T_H
+#ifndef LLVM_LIBC_TYPES_X86_64_UCONTEXT_T_H
+#define LLVM_LIBC_TYPES_X86_64_UCONTEXT_T_H
#include "../sigset_t.h"
#include "../stack_t.h"
@@ -40,4 +40,4 @@ typedef struct alignas(16) ucontext_t {
unsigned long long __ssp[4];
} ucontext_t;
-#endif // LLVM_LIBC_TYPES_UCONTEXT_T_H
+#endif // LLVM_LIBC_TYPES_X86_64_UCONTEXT_T_H
diff --git a/libc/src/ucontext/x86_64/getcontext.cpp b/libc/src/ucontext/x86_64/getcontext.cpp
index 082599bb6017a..bd0fb5522f2bf 100644
--- a/libc/src/ucontext/x86_64/getcontext.cpp
+++ b/libc/src/ucontext/x86_64/getcontext.cpp
@@ -76,39 +76,39 @@ LLVM_LIBC_FUNCTION(int, getcontext, (ucontext_t * ucp)) {
[sigset_size] "i"(sizeof(sigset_t)),
[syscall_num] "i"(SYS_rt_sigprocmask),
[r8] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R8])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_R8])),
[r9] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R9])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_R9])),
[r10] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R10])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_R10])),
[r11] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R11])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_R11])),
[r12] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R12])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_R12])),
[r13] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R13])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_R13])),
[r14] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R14])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_R14])),
[r15] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R15])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_R15])),
[rdi] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RDI])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RDI])),
[rsi] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RSI])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RSI])),
[rbp] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RBP])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RBP])),
[rbx] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RBX])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RBX])),
[rdx] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RDX])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RDX])),
[rax] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RAX])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RAX])),
[rcx] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RCX])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RCX])),
[rsp] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RSP])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RSP])),
[rip] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RIP])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RIP])),
[fpregs_mem] "i"(__builtin_offsetof(ucontext_t, __fpregs_mem)),
[fpregs_ptr] "i"(__builtin_offsetof(ucontext_t, uc_mcontext.fpregs)),
[sigmask] "i"(__builtin_offsetof(ucontext_t, uc_sigmask))
diff --git a/libc/src/ucontext/x86_64/makecontext.cpp b/libc/src/ucontext/x86_64/makecontext.cpp
index 7a757d3f42251..66b185d71dca3 100644
--- a/libc/src/ucontext/x86_64/makecontext.cpp
+++ b/libc/src/ucontext/x86_64/makecontext.cpp
@@ -67,17 +67,17 @@ LLVM_LIBC_FUNCTION(void, makecontext,
va_list ap;
va_start(ap, argc);
if (argc > 0)
- ucp->uc_mcontext.gregs[__LIBC_REG_RDI] = va_arg(ap, greg_t);
+ ucp->uc_mcontext.gregs[REG_RDI] = va_arg(ap, greg_t);
if (argc > 1)
- ucp->uc_mcontext.gregs[__LIBC_REG_RSI] = va_arg(ap, greg_t);
+ ucp->uc_mcontext.gregs[REG_RSI] = va_arg(ap, greg_t);
if (argc > 2)
- ucp->uc_mcontext.gregs[__LIBC_REG_RDX] = va_arg(ap, greg_t);
+ ucp->uc_mcontext.gregs[REG_RDX] = va_arg(ap, greg_t);
if (argc > 3)
- ucp->uc_mcontext.gregs[__LIBC_REG_RCX] = va_arg(ap, greg_t);
+ ucp->uc_mcontext.gregs[REG_RCX] = va_arg(ap, greg_t);
if (argc > 4)
- ucp->uc_mcontext.gregs[__LIBC_REG_R8] = va_arg(ap, greg_t);
+ ucp->uc_mcontext.gregs[REG_R8] = va_arg(ap, greg_t);
if (argc > 5)
- ucp->uc_mcontext.gregs[__LIBC_REG_R9] = va_arg(ap, greg_t);
+ ucp->uc_mcontext.gregs[REG_R9] = va_arg(ap, greg_t);
for (int i = 0; i < stack_args; ++i) {
stack_area[i + 1] = va_arg(ap, greg_t);
@@ -85,9 +85,9 @@ LLVM_LIBC_FUNCTION(void, makecontext,
va_end(ap);
- ucp->uc_mcontext.gregs[__LIBC_REG_RIP] = reinterpret_cast<greg_t>(func);
- ucp->uc_mcontext.gregs[__LIBC_REG_RSP] = new_rsp;
- ucp->uc_mcontext.gregs[__LIBC_REG_RBX] =
+ ucp->uc_mcontext.gregs[REG_RIP] = reinterpret_cast<greg_t>(func);
+ ucp->uc_mcontext.gregs[REG_RSP] = new_rsp;
+ ucp->uc_mcontext.gregs[REG_RBX] =
reinterpret_cast<greg_t>(ucp->uc_link);
}
diff --git a/libc/src/ucontext/x86_64/setcontext.cpp b/libc/src/ucontext/x86_64/setcontext.cpp
index 95ca78e239085..b4acec966a80d 100644
--- a/libc/src/ucontext/x86_64/setcontext.cpp
+++ b/libc/src/ucontext/x86_64/setcontext.cpp
@@ -62,39 +62,39 @@ LLVM_LIBC_FUNCTION(int, setcontext, (const ucontext_t *ucp)) {
)" ::[sigset_size] "i"(sizeof(sigset_t)),
[syscall_num] "i"(SYS_rt_sigprocmask),
[r8] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R8])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_R8])),
[r9] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R9])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_R9])),
[r10] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R10])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_R10])),
[r11] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R11])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_R11])),
[r12] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R12])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_R12])),
[r13] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R13])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_R13])),
[r14] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R14])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_R14])),
[r15] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R15])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_R15])),
[rdi] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RDI])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RDI])),
[rsi] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RSI])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RSI])),
[rbp] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RBP])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RBP])),
[rbx] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RBX])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RBX])),
[rdx] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RDX])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RDX])),
[rax] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RAX])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RAX])),
[rcx] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RCX])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RCX])),
[rsp] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RSP])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RSP])),
[rip] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RIP])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RIP])),
[fpregs_mem] "i"(__builtin_offsetof(ucontext_t, __fpregs_mem)),
[sigmask] "i"(__builtin_offsetof(ucontext_t, uc_sigmask))
: "memory", "rcx", "r11");
diff --git a/libc/src/ucontext/x86_64/swapcontext.cpp b/libc/src/ucontext/x86_64/swapcontext.cpp
index 7115e5c4059f1..2410f092bdff9 100644
--- a/libc/src/ucontext/x86_64/swapcontext.cpp
+++ b/libc/src/ucontext/x86_64/swapcontext.cpp
@@ -102,39 +102,39 @@ LLVM_LIBC_FUNCTION(int, swapcontext,
[sigset_size] "i"(sizeof(sigset_t)),
[syscall_num] "i"(SYS_rt_sigprocmask),
[r8] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R8])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_R8])),
[r9] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R9])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_R9])),
[r10] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R10])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_R10])),
[r11] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R11])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_R11])),
[r12] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R12])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_R12])),
[r13] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R13])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_R13])),
[r14] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R14])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_R14])),
[r15] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_R15])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_R15])),
[rdi] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RDI])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RDI])),
[rsi] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RSI])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RSI])),
[rbp] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RBP])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RBP])),
[rbx] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RBX])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RBX])),
[rdx] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RDX])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RDX])),
[rax] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RAX])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RAX])),
[rcx] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RCX])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RCX])),
[rsp] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RSP])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RSP])),
[rip] "i"(
- __builtin_offsetof(ucontext_t, uc_mcontext.gregs[__LIBC_REG_RIP])),
+ __builtin_offsetof(ucontext_t, uc_mcontext.gregs[REG_RIP])),
[fpregs_mem] "i"(__builtin_offsetof(ucontext_t, __fpregs_mem)),
[fpregs_ptr] "i"(__builtin_offsetof(ucontext_t, uc_mcontext.fpregs)),
[sigmask] "i"(__builtin_offsetof(ucontext_t, uc_sigmask))
More information about the libc-commits
mailing list