[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