[libc-commits] [libc] [libc] Implement ucontext functions for x86_64 (PR #187712)
via libc-commits
libc-commits at lists.llvm.org
Fri Mar 20 07:47:20 PDT 2026
github-actions[bot] wrote:
<!--LLVM CODE FORMAT COMMENT: {clang-format}-->
:warning: C/C++ code formatter, clang-format found issues in your code. :warning:
<details>
<summary>
You can test this locally with the following command:
</summary>
``````````bash
git-clang-format --diff origin/main HEAD --extensions cpp,h -- libc/include/llvm-libc-types/mcontext_t.h libc/include/llvm-libc-types/ucontext_t.h libc/src/ucontext/getcontext.h libc/src/ucontext/makecontext.h libc/src/ucontext/setcontext.h libc/src/ucontext/swapcontext.h libc/src/ucontext/x86_64/getcontext.cpp libc/src/ucontext/x86_64/makecontext.cpp libc/src/ucontext/x86_64/setcontext.cpp libc/src/ucontext/x86_64/swapcontext.cpp libc/test/src/ucontext/ucontext_test.cpp --diff_from_common_commit
``````````
:warning:
The reproduction instructions above might return results for more than one PR
in a stack if you are using a stacked PR workflow. You can limit the results by
changing `origin/main` to the base branch/commit you want to compare against.
:warning:
</details>
<details>
<summary>
View the diff from clang-format here.
</summary>
``````````diff
diff --git a/libc/src/ucontext/getcontext.h b/libc/src/ucontext/getcontext.h
index b8f1ef46e..804feed18 100644
--- a/libc/src/ucontext/getcontext.h
+++ b/libc/src/ucontext/getcontext.h
@@ -1,4 +1,5 @@
-//===-- Implementation header for getcontext ----------------------*- C++ -*-===//
+//===-- 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.
@@ -9,8 +10,8 @@
#ifndef LLVM_LIBC_SRC_UCONTEXT_GETCONTEXT_H
#define LLVM_LIBC_SRC_UCONTEXT_GETCONTEXT_H
-#include "src/__support/macros/config.h"
#include "include/llvm-libc-types/ucontext_t.h"
+#include "src/__support/macros/config.h"
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/ucontext/makecontext.h b/libc/src/ucontext/makecontext.h
index 78e799983..ebf4e48b8 100644
--- a/libc/src/ucontext/makecontext.h
+++ b/libc/src/ucontext/makecontext.h
@@ -1,4 +1,5 @@
-//===-- Implementation header for makecontext ---------------------*- C++ -*-===//
+//===-- 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.
@@ -9,8 +10,8 @@
#ifndef LLVM_LIBC_SRC_UCONTEXT_MAKECONTEXT_H
#define LLVM_LIBC_SRC_UCONTEXT_MAKECONTEXT_H
-#include "src/__support/macros/config.h"
#include "include/llvm-libc-types/ucontext_t.h"
+#include "src/__support/macros/config.h"
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/ucontext/setcontext.h b/libc/src/ucontext/setcontext.h
index e5fbac6da..c42feb1fe 100644
--- a/libc/src/ucontext/setcontext.h
+++ b/libc/src/ucontext/setcontext.h
@@ -1,4 +1,5 @@
-//===-- Implementation header for setcontext ----------------------*- C++ -*-===//
+//===-- 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.
@@ -9,8 +10,8 @@
#ifndef LLVM_LIBC_SRC_UCONTEXT_SETCONTEXT_H
#define LLVM_LIBC_SRC_UCONTEXT_SETCONTEXT_H
-#include "src/__support/macros/config.h"
#include "include/llvm-libc-types/ucontext_t.h"
+#include "src/__support/macros/config.h"
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/ucontext/swapcontext.h b/libc/src/ucontext/swapcontext.h
index 4412c862a..c35490aed 100644
--- a/libc/src/ucontext/swapcontext.h
+++ b/libc/src/ucontext/swapcontext.h
@@ -1,4 +1,5 @@
-//===-- Implementation header for swapcontext ---------------------*- C++ -*-===//
+//===-- 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.
@@ -9,8 +10,8 @@
#ifndef LLVM_LIBC_SRC_UCONTEXT_SWAPCONTEXT_H
#define LLVM_LIBC_SRC_UCONTEXT_SWAPCONTEXT_H
-#include "src/__support/macros/config.h"
#include "include/llvm-libc-types/ucontext_t.h"
+#include "src/__support/macros/config.h"
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/ucontext/x86_64/getcontext.cpp b/libc/src/ucontext/x86_64/getcontext.cpp
index f49987320..c0d27835f 100644
--- a/libc/src/ucontext/x86_64/getcontext.cpp
+++ b/libc/src/ucontext/x86_64/getcontext.cpp
@@ -21,7 +21,7 @@ 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)) {
+LLVM_LIBC_FUNCTION(int, getcontext, (ucontext_t * ucp)) {
asm(R"(
// ucp is in rdi
@@ -65,9 +65,7 @@ LLVM_LIBC_FUNCTION(int, getcontext, (ucontext_t *ucp)) {
// Signal support is currently minimal in LLVM-libc.
retq
- )"
- ::
- [ret_size] "i"(sizeof(void*)),
+ )" ::[ret_size] "i"(sizeof(void *)),
[r8] "i"(offsetof(ucontext_t, uc_mcontext.gregs[REG_R8])),
[r9] "i"(offsetof(ucontext_t, uc_mcontext.gregs[REG_R9])),
[r10] "i"(offsetof(ucontext_t, uc_mcontext.gregs[REG_R10])),
@@ -87,8 +85,7 @@ LLVM_LIBC_FUNCTION(int, getcontext, (ucontext_t *ucp)) {
[rip] "i"(offsetof(ucontext_t, uc_mcontext.gregs[REG_RIP])),
[fpregs_mem] "i"(offsetof(ucontext_t, __fpregs_mem)),
[fpregs_ptr] "i"(offsetof(ucontext_t, uc_mcontext.fpregs))
- : "memory"
- );
+ : "memory");
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/ucontext/x86_64/makecontext.cpp b/libc/src/ucontext/x86_64/makecontext.cpp
index 8907dab4f..f316f9b34 100644
--- a/libc/src/ucontext/x86_64/makecontext.cpp
+++ b/libc/src/ucontext/x86_64/makecontext.cpp
@@ -11,9 +11,9 @@
#include "src/__support/macros/config.h"
#include "include/llvm-libc-types/ucontext_t.h"
+#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
-#include <stdarg.h>
#include "src/__support/OSUtil/exit.h"
#include "src/ucontext/setcontext.h"
@@ -23,7 +23,7 @@ namespace LIBC_NAMESPACE_DECL {
extern "C" void __makecontext_trampoline_c(ucontext_t *uc_link) {
if (uc_link)
setcontext(uc_link);
-
+
internal::exit(0);
}
@@ -35,7 +35,8 @@ extern "C" void __makecontext_trampoline_c(ucontext_t *uc_link) {
)");
}
-LLVM_LIBC_FUNCTION(void, makecontext, (ucontext_t *ucp, void (*func)(void), int argc, ...)) {
+LLVM_LIBC_FUNCTION(void, makecontext,
+ (ucontext_t * ucp, void (*func)(void), int argc, ...)) {
if (!ucp || !func)
return;
@@ -45,17 +46,19 @@ LLVM_LIBC_FUNCTION(void, makecontext, (ucontext_t *ucp, void (*func)(void), int
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;
+ 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.
+
+ // 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);
@@ -63,17 +66,23 @@ LLVM_LIBC_FUNCTION(void, makecontext, (ucontext_t *ucp, void (*func)(void), int
va_list ap;
va_start(ap, argc);
- if (argc > 0) ucp->uc_mcontext.gregs[REG_RDI] = va_arg(ap, greg_t);
- if (argc > 1) ucp->uc_mcontext.gregs[REG_RSI] = va_arg(ap, greg_t);
- if (argc > 2) ucp->uc_mcontext.gregs[REG_RDX] = va_arg(ap, greg_t);
- if (argc > 3) ucp->uc_mcontext.gregs[REG_RCX] = va_arg(ap, greg_t);
- if (argc > 4) ucp->uc_mcontext.gregs[REG_R8] = va_arg(ap, greg_t);
- if (argc > 5) ucp->uc_mcontext.gregs[REG_R9] = va_arg(ap, greg_t);
-
+ if (argc > 0)
+ ucp->uc_mcontext.gregs[REG_RDI] = va_arg(ap, greg_t);
+ if (argc > 1)
+ ucp->uc_mcontext.gregs[REG_RSI] = va_arg(ap, greg_t);
+ if (argc > 2)
+ ucp->uc_mcontext.gregs[REG_RDX] = va_arg(ap, greg_t);
+ if (argc > 3)
+ ucp->uc_mcontext.gregs[REG_RCX] = va_arg(ap, greg_t);
+ if (argc > 4)
+ ucp->uc_mcontext.gregs[REG_R8] = va_arg(ap, greg_t);
+ if (argc > 5)
+ 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);
}
-
+
va_end(ap);
ucp->uc_mcontext.gregs[REG_RIP] = reinterpret_cast<greg_t>(func);
diff --git a/libc/src/ucontext/x86_64/setcontext.cpp b/libc/src/ucontext/x86_64/setcontext.cpp
index 43aa45ba2..d77889669 100644
--- a/libc/src/ucontext/x86_64/setcontext.cpp
+++ b/libc/src/ucontext/x86_64/setcontext.cpp
@@ -64,9 +64,7 @@ LLVM_LIBC_FUNCTION(int, setcontext, (const ucontext_t *ucp)) {
// General registers are restored.
// Jump and continue!
retq
- )"
- ::
- [r8] "i"(offsetof(ucontext_t, uc_mcontext.gregs[REG_R8])),
+ )" ::[r8] "i"(offsetof(ucontext_t, uc_mcontext.gregs[REG_R8])),
[r9] "i"(offsetof(ucontext_t, uc_mcontext.gregs[REG_R9])),
[r10] "i"(offsetof(ucontext_t, uc_mcontext.gregs[REG_R10])),
[r11] "i"(offsetof(ucontext_t, uc_mcontext.gregs[REG_R11])),
@@ -83,8 +81,7 @@ LLVM_LIBC_FUNCTION(int, setcontext, (const ucontext_t *ucp)) {
[rcx] "i"(offsetof(ucontext_t, uc_mcontext.gregs[REG_RCX])),
[rsp] "i"(offsetof(ucontext_t, uc_mcontext.gregs[REG_RSP])),
[rip] "i"(offsetof(ucontext_t, uc_mcontext.gregs[REG_RIP])),
- [fpregs_mem] "i"(offsetof(ucontext_t, __fpregs_mem))
- );
+ [fpregs_mem] "i"(offsetof(ucontext_t, __fpregs_mem)));
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/ucontext/x86_64/swapcontext.cpp b/libc/src/ucontext/x86_64/swapcontext.cpp
index ba50df669..4dec9cb20 100644
--- a/libc/src/ucontext/x86_64/swapcontext.cpp
+++ b/libc/src/ucontext/x86_64/swapcontext.cpp
@@ -15,7 +15,9 @@
namespace LIBC_NAMESPACE_DECL {
[[gnu::naked]]
-LLVM_LIBC_FUNCTION(int, swapcontext, (ucontext_t *__restrict oucp, const ucontext_t *__restrict ucp)) {
+LLVM_LIBC_FUNCTION(int, swapcontext,
+ (ucontext_t *__restrict oucp,
+ const ucontext_t *__restrict ucp)) {
asm(R"(
// oucp is in rdi, ucp is in rsi
@@ -78,9 +80,7 @@ LLVM_LIBC_FUNCTION(int, swapcontext, (ucontext_t *__restrict oucp, const ucontex
mov %c[rsi](%%rsi), %%rsi
retq
- )"
- ::
- [ret_size] "i"(sizeof(void*)),
+ )" ::[ret_size] "i"(sizeof(void *)),
[r8] "i"(offsetof(ucontext_t, uc_mcontext.gregs[REG_R8])),
[r9] "i"(offsetof(ucontext_t, uc_mcontext.gregs[REG_R9])),
[r10] "i"(offsetof(ucontext_t, uc_mcontext.gregs[REG_R10])),
@@ -100,8 +100,7 @@ LLVM_LIBC_FUNCTION(int, swapcontext, (ucontext_t *__restrict oucp, const ucontex
[rip] "i"(offsetof(ucontext_t, uc_mcontext.gregs[REG_RIP])),
[fpregs_mem] "i"(offsetof(ucontext_t, __fpregs_mem)),
[fpregs_ptr] "i"(offsetof(ucontext_t, uc_mcontext.fpregs))
- : "memory"
- );
+ : "memory");
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/src/ucontext/ucontext_test.cpp b/libc/test/src/ucontext/ucontext_test.cpp
index c74f0a8c3..3f5d57ec4 100644
--- a/libc/test/src/ucontext/ucontext_test.cpp
+++ b/libc/test/src/ucontext/ucontext_test.cpp
@@ -7,8 +7,8 @@
//===----------------------------------------------------------------------===//
#include "src/ucontext/getcontext.h"
-#include "src/ucontext/setcontext.h"
#include "src/ucontext/makecontext.h"
+#include "src/ucontext/setcontext.h"
#include "src/ucontext/swapcontext.h"
#include "test/UnitTest/Test.h"
@@ -43,7 +43,7 @@ TEST(LlvmLibcUcontextTest, SwapcontextTest) {
LIBC_NAMESPACE::makecontext(&new_ctx, swap_func, 0);
LIBC_NAMESPACE::swapcontext(&old_ctx, &new_ctx);
-
+
ASSERT_EQ(swap_called, 1);
}
@@ -53,8 +53,14 @@ 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;
+ arg1 = a1;
+ arg2 = a2;
+ arg3 = a3;
+ arg4 = a4;
+ arg5 = a5;
+ arg6 = a6;
+ arg7 = a7;
+ arg8 = a8;
LIBC_NAMESPACE::setcontext(&old_ctx_args);
}
@@ -64,15 +70,16 @@ TEST(LlvmLibcUcontextTest, MakecontextArgsTest) {
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);
-
- LIBC_NAMESPACE::makecontext(&new_ctx_args, func, 8, 11, 22, 33, 44, 55, 66, 77, 88);
+
+ LIBC_NAMESPACE::makecontext(&new_ctx_args, func, 8, 11, 22, 33, 44, 55, 66,
+ 77, 88);
LIBC_NAMESPACE::swapcontext(&old_ctx_args, &new_ctx_args);
-
+
ASSERT_EQ(makecontext_args_called, 1);
ASSERT_EQ(arg1, 11);
ASSERT_EQ(arg2, 22);
@@ -86,9 +93,7 @@ TEST(LlvmLibcUcontextTest, MakecontextArgsTest) {
ucontext_t old_ctx_return, new_ctx_return;
volatile int makecontext_return_called = 0;
-void return_func() {
- makecontext_return_called = 1;
-}
+void return_func() { makecontext_return_called = 1; }
TEST(LlvmLibcUcontextTest, MakecontextReturnTest) {
LIBC_NAMESPACE::getcontext(&new_ctx_return);
@@ -97,13 +102,13 @@ TEST(LlvmLibcUcontextTest, MakecontextReturnTest) {
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);
-
+
LIBC_NAMESPACE::makecontext(&new_ctx_return, func, 0);
LIBC_NAMESPACE::swapcontext(&old_ctx_return, &new_ctx_return);
-
+
ASSERT_EQ(makecontext_return_called, 1);
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/187712
More information about the libc-commits
mailing list