-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[libc] implement sigsetjmp/siglongjmp for riscv #137992
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-libc Author: Schrodinger ZHU Yifan (SchrodingerZhu) ChangesFull diff: https://github.com/llvm/llvm-project/pull/137992.diff 4 Files Affected:
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index f2f895117e35a..e0b20e4ff24b5 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -877,6 +877,8 @@ if(LLVM_LIBC_FULL_BUILD)
# setjmp.h entrypoints
libc.src.setjmp.longjmp
libc.src.setjmp.setjmp
+ libc.src.setjmp.siglongjmp
+ libc.src.setjmp.sigsetjmp
# stdio.h entrypoints
libc.src.stdio.clearerr
diff --git a/libc/include/llvm-libc-types/jmp_buf.h b/libc/include/llvm-libc-types/jmp_buf.h
index 7e7d2da8a932a..2fec35dbc9163 100644
--- a/libc/include/llvm-libc-types/jmp_buf.h
+++ b/libc/include/llvm-libc-types/jmp_buf.h
@@ -12,7 +12,8 @@
// TODO: implement sigjmp_buf related functions for other architectures
// Issue: https://github.com/llvm/llvm-project/issues/136358
#if defined(__linux__)
-#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || \
+ defined(__riscv)
#define __LIBC_HAS_SIGJMP_BUF
#endif
#endif
diff --git a/libc/src/setjmp/riscv/CMakeLists.txt b/libc/src/setjmp/riscv/CMakeLists.txt
index c68e318a0f08b..1959e9c905e23 100644
--- a/libc/src/setjmp/riscv/CMakeLists.txt
+++ b/libc/src/setjmp/riscv/CMakeLists.txt
@@ -11,6 +11,22 @@ add_entrypoint_object(
-fomit-frame-pointer
)
+if (TARGET libc.src.setjmp.sigsetjmp_epilogue)
+ add_entrypoint_object(
+ sigsetjmp
+ SRCS
+ sigsetjmp.cpp
+ HDRS
+ ../sigsetjmp.h
+ DEPENDS
+ libc.hdr.types.jmp_buf
+ libc.hdr.types.sigset_t
+ libc.hdr.offsetof_macros
+ libc.src.setjmp.sigsetjmp_epilogue
+ libc.src.setjmp.setjmp
+ )
+endif()
+
add_entrypoint_object(
longjmp
SRCS
diff --git a/libc/src/setjmp/riscv/sigsetjmp.cpp b/libc/src/setjmp/riscv/sigsetjmp.cpp
new file mode 100644
index 0000000000000..2c6d44203e150
--- /dev/null
+++ b/libc/src/setjmp/riscv/sigsetjmp.cpp
@@ -0,0 +1,49 @@
+//===-- Implementation of sigsetjmp ---------------------------------------===//
+//
+// 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/setjmp/sigsetjmp.h"
+#include "hdr/offsetof_macros.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/setjmp/setjmp_impl.h"
+#include "src/setjmp/sigsetjmp_epilogue.h"
+
+#if __riscv_xlen == 64
+#define STORE(A, B, C) "sd " #A ", %c[" #B "](" #C ")\n\t"
+#define LOAD(A, B, C) "ld " #A ", %c[" #B "](" #C ")\n\t"
+#elif __riscv_xlen == 32
+#define STORE(A, B, C) "sw " #A ", %c[" #B "](" #C ")\n\t"
+#define LOAD(A, B, C) "lw " #A ", %c[" #B "](" #C ")\n\t"
+#else
+#error "Unsupported RISC-V architecture"
+#endif
+
+namespace LIBC_NAMESPACE_DECL {
+[[gnu::naked]]
+LLVM_LIBC_FUNCTION(int, sigsetjmp, (sigjmp_buf, int)) {
+ // clang-format off
+ asm("beqz a1, .Lnosave\n\t"
+ STORE(ra, retaddr, a0)
+ STORE(s0, extra, a0)
+ "mv s0, a0\n\t"
+ "call %c[setjmp]\n\t"
+ "mv a1, a0\n\t"
+ "mv a0, s0\n\t"
+ LOAD(s0, extra, a0)
+ LOAD(ra, retaddr, a0)
+ "tail %c[epilogue]\n"
+".Lnosave:\n\t"
+ "tail %c[setjmp]"
+ // clang-format on
+ ::[retaddr] "i"(offsetof(__jmp_buf, sig_retaddr)),
+ [extra] "i"(offsetof(__jmp_buf, sig_extra)), [setjmp] "i"(setjmp),
+ [epilogue] "i"(sigsetjmp_epilogue)
+ : "a0", "a1", "s0");
+}
+
+} // namespace LIBC_NAMESPACE_DECL
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements support for sigsetjmp and siglongjmp on RISC-V architectures in LLVM’s libc. It adds a new source file implementing sigsetjmp with inline assembly, updates the header for jmp_buf types to include RISC-V, and configures the build system on Linux to recognize the new entrypoints.
Reviewed Changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated no comments.
File | Description |
---|---|
libc/src/setjmp/riscv/sigsetjmp.cpp | Implements sigsetjmp for RISC-V using inline assembly macros. |
libc/include/llvm-libc-types/jmp_buf.h | Updates jmp_buf condition to include RISC-V architectures. |
libc/config/linux/riscv/entrypoints.txt | Registers the new sigsetjmp/siglongjmp entrypoints for RISC-V. |
Files not reviewed (1)
- libc/src/setjmp/riscv/CMakeLists.txt: Language not supported
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
Tests pass in both rv32 and rv64
See https://godbolt.org/z/jo7s6j7sq for compiled code. ```c++ #if __riscv_xlen == 64 #define STORE(A, B, C) "sd " #A ", %c[" #B "](" #C ")\n\t" #define LOAD(A, B, C) "ld " #A ", %c[" #B "](" #C ")\n\t" #elif __riscv_xlen == 32 #define STORE(A, B, C) "sw " #A ", %c[" #B "](" #C ")\n\t" #define LOAD(A, B, C) "lw " #A ", %c[" #B "](" #C ")\n\t" #else #error "Unsupported RISC-V architecture" #endif namespace LIBC_NAMESPACE_DECL { [[gnu::naked]] LLVM_LIBC_FUNCTION(int, sigsetjmp, (sigjmp_buf, int)) { // clang-format off asm("beqz a1, .Lnosave\n\t" STORE(ra, retaddr, a0) STORE(s0, extra, a0) "mv s0, a0\n\t" "call %c[setjmp]\n\t" "mv a1, a0\n\t" "mv a0, s0\n\t" LOAD(s0, extra, a0) LOAD(ra, retaddr, a0) "tail %c[epilogue]\n" ".Lnosave:\n\t" "tail %c[setjmp]" // clang-format on ::[retaddr] "i"(offsetof(__jmp_buf, sig_retaddr)), [extra] "i"(offsetof(__jmp_buf, sig_extra)), [setjmp] "i"(setjmp), [epilogue] "i"(sigsetjmp_epilogue) : "a0", "a1", "s0"); } ```
See https://godbolt.org/z/jo7s6j7sq for compiled code. ```c++ #if __riscv_xlen == 64 #define STORE(A, B, C) "sd " #A ", %c[" #B "](" #C ")\n\t" #define LOAD(A, B, C) "ld " #A ", %c[" #B "](" #C ")\n\t" #elif __riscv_xlen == 32 #define STORE(A, B, C) "sw " #A ", %c[" #B "](" #C ")\n\t" #define LOAD(A, B, C) "lw " #A ", %c[" #B "](" #C ")\n\t" #else #error "Unsupported RISC-V architecture" #endif namespace LIBC_NAMESPACE_DECL { [[gnu::naked]] LLVM_LIBC_FUNCTION(int, sigsetjmp, (sigjmp_buf, int)) { // clang-format off asm("beqz a1, .Lnosave\n\t" STORE(ra, retaddr, a0) STORE(s0, extra, a0) "mv s0, a0\n\t" "call %c[setjmp]\n\t" "mv a1, a0\n\t" "mv a0, s0\n\t" LOAD(s0, extra, a0) LOAD(ra, retaddr, a0) "tail %c[epilogue]\n" ".Lnosave:\n\t" "tail %c[setjmp]" // clang-format on ::[retaddr] "i"(offsetof(__jmp_buf, sig_retaddr)), [extra] "i"(offsetof(__jmp_buf, sig_extra)), [setjmp] "i"(setjmp), [epilogue] "i"(sigsetjmp_epilogue) : "a0", "a1", "s0"); } ```
See https://godbolt.org/z/jo7s6j7sq for compiled code. ```c++ #if __riscv_xlen == 64 #define STORE(A, B, C) "sd " #A ", %c[" #B "](" #C ")\n\t" #define LOAD(A, B, C) "ld " #A ", %c[" #B "](" #C ")\n\t" #elif __riscv_xlen == 32 #define STORE(A, B, C) "sw " #A ", %c[" #B "](" #C ")\n\t" #define LOAD(A, B, C) "lw " #A ", %c[" #B "](" #C ")\n\t" #else #error "Unsupported RISC-V architecture" #endif namespace LIBC_NAMESPACE_DECL { [[gnu::naked]] LLVM_LIBC_FUNCTION(int, sigsetjmp, (sigjmp_buf, int)) { // clang-format off asm("beqz a1, .Lnosave\n\t" STORE(ra, retaddr, a0) STORE(s0, extra, a0) "mv s0, a0\n\t" "call %c[setjmp]\n\t" "mv a1, a0\n\t" "mv a0, s0\n\t" LOAD(s0, extra, a0) LOAD(ra, retaddr, a0) "tail %c[epilogue]\n" ".Lnosave:\n\t" "tail %c[setjmp]" // clang-format on ::[retaddr] "i"(offsetof(__jmp_buf, sig_retaddr)), [extra] "i"(offsetof(__jmp_buf, sig_extra)), [setjmp] "i"(setjmp), [epilogue] "i"(sigsetjmp_epilogue) : "a0", "a1", "s0"); } ```
See https://godbolt.org/z/jo7s6j7sq for compiled code. ```c++ #if __riscv_xlen == 64 #define STORE(A, B, C) "sd " #A ", %c[" #B "](" #C ")\n\t" #define LOAD(A, B, C) "ld " #A ", %c[" #B "](" #C ")\n\t" #elif __riscv_xlen == 32 #define STORE(A, B, C) "sw " #A ", %c[" #B "](" #C ")\n\t" #define LOAD(A, B, C) "lw " #A ", %c[" #B "](" #C ")\n\t" #else #error "Unsupported RISC-V architecture" #endif namespace LIBC_NAMESPACE_DECL { [[gnu::naked]] LLVM_LIBC_FUNCTION(int, sigsetjmp, (sigjmp_buf, int)) { // clang-format off asm("beqz a1, .Lnosave\n\t" STORE(ra, retaddr, a0) STORE(s0, extra, a0) "mv s0, a0\n\t" "call %c[setjmp]\n\t" "mv a1, a0\n\t" "mv a0, s0\n\t" LOAD(s0, extra, a0) LOAD(ra, retaddr, a0) "tail %c[epilogue]\n" ".Lnosave:\n\t" "tail %c[setjmp]" // clang-format on ::[retaddr] "i"(offsetof(__jmp_buf, sig_retaddr)), [extra] "i"(offsetof(__jmp_buf, sig_extra)), [setjmp] "i"(setjmp), [epilogue] "i"(sigsetjmp_epilogue) : "a0", "a1", "s0"); } ```
See https://godbolt.org/z/jo7s6j7sq for compiled code.