-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[libc][setjmp] make x86_64 longjmp naked #112581
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
The generated asm for x86_64's longjmp has a function prolog and epilog. The epilog in particular is unreachable. Convert longjmp to a naked function to avoid these spurious instructions in longjmp. Link: https://github.com/llvm/llvm-project/pull/112437/files#r1802085511
@llvm/pr-subscribers-libc Author: Nick Desaulniers (nickdesaulniers) ChangesThe generated asm for x86_64's longjmp has a function prolog and epilog. The Link: https://github.com/llvm/llvm-project/pull/112437/files#r1802085511 Full diff: https://github.com/llvm/llvm-project/pull/112581.diff 2 Files Affected:
diff --git a/libc/src/setjmp/longjmp.h b/libc/src/setjmp/longjmp.h
index 7cb12b3392ae16..9b7db29717216b 100644
--- a/libc/src/setjmp/longjmp.h
+++ b/libc/src/setjmp/longjmp.h
@@ -11,9 +11,22 @@
#include "hdr/types/jmp_buf.h"
#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/compiler.h"
namespace LIBC_NAMESPACE_DECL {
+// TODO(https://github.com/llvm/llvm-project/issues/112427)
+// Some of the architecture-specific definitions are marked `naked`, which in
+// GCC implies `nothrow`.
+//
+// Right now, our aliases aren't marked `nothrow`, so we wind up in a situation
+// where clang will emit -Wmissing-exception-spec if we add `nothrow` here, but
+// GCC will emit -Wmissing-attributes here without `nothrow`. We need to update
+// LLVM_LIBC_FUNCTION to denote when a function throws or not.
+
+#ifdef LIBC_COMPILER_IS_GCC
+[[gnu::nothrow]]
+#endif
void longjmp(jmp_buf buf, int val);
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/setjmp/x86_64/longjmp.cpp b/libc/src/setjmp/x86_64/longjmp.cpp
index d4b55565cb2187..5d5da673348ede 100644
--- a/libc/src/setjmp/x86_64/longjmp.cpp
+++ b/libc/src/setjmp/x86_64/longjmp.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "src/setjmp/longjmp.h"
+#include "include/llvm-libc-macros/offsetof-macro.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
@@ -16,30 +17,31 @@
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(void, longjmp, (jmp_buf buf, int val)) {
- register __UINT64_TYPE__ rbx __asm__("rbx");
- register __UINT64_TYPE__ rbp __asm__("rbp");
- register __UINT64_TYPE__ r12 __asm__("r12");
- register __UINT64_TYPE__ r13 __asm__("r13");
- register __UINT64_TYPE__ r14 __asm__("r14");
- register __UINT64_TYPE__ r15 __asm__("r15");
- register __UINT64_TYPE__ rsp __asm__("rsp");
- register __UINT64_TYPE__ rax __asm__("rax");
+[[gnu::naked]]
+LLVM_LIBC_FUNCTION(void, longjmp, (jmp_buf, int)) {
+ asm(R"(
+ cmpl $0x1, %%esi
+ adcl $0x0, %%esi
+ movq %%rsi, %%rax
- // ABI requires that the return value should be stored in rax. So, we store
- // |val| in rax. Note that this has to happen before we restore the registers
- // from values in |buf|. Otherwise, once rsp and rbp are updated, we cannot
- // read |val|.
- val = val == 0 ? 1 : val;
- LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(rax) : "m"(val) :);
- LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(rbx) : "m"(buf->rbx) :);
- LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(rbp) : "m"(buf->rbp) :);
- LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(r12) : "m"(buf->r12) :);
- LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(r13) : "m"(buf->r13) :);
- LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(r14) : "m"(buf->r14) :);
- LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(r15) : "m"(buf->r15) :);
- LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(rsp) : "m"(buf->rsp) :);
- LIBC_INLINE_ASM("jmp *%0\n\t" : : "m"(buf->rip));
+ movq %c[rbx](%%rdi), %%rbx
+ movq %c[rbp](%%rdi), %%rbp
+ movq %c[r12](%%rdi), %%r12
+ movq %c[r13](%%rdi), %%r13
+ movq %c[r14](%%rdi), %%r14
+ movq %c[r15](%%rdi), %%r15
+ movq %c[rsp](%%rdi), %%rsp
+ jmpq *%c[rip](%%rdi)
+ )" ::
+ [rbx] "i"(offsetof(__jmp_buf, rbx)),
+ [rbp] "i"(offsetof(__jmp_buf, rbp)),
+ [r12] "i"(offsetof(__jmp_buf, r12)),
+ [r13] "i"(offsetof(__jmp_buf, r13)),
+ [r14] "i"(offsetof(__jmp_buf, r14)),
+ [r15] "i"(offsetof(__jmp_buf, r15)),
+ [rsp] "i"(offsetof(__jmp_buf, rsp)),
+ [rip] "i"(offsetof(__jmp_buf, rip))
+);
}
} // namespace LIBC_NAMESPACE_DECL
|
@SchrodingerZhu this might complicate your patch. |
I will rework the chksum then. no worries |
✅ With the latest revision this PR passed the C/C++ code formatter. |
merge according to previous approval |
The generated asm for x86_64's longjmp has a function prolog and epilog. The
epilog in particular is unreachable. Convert longjmp to a naked function to
avoid these spurious instructions in longjmp.
Link: https://github.com/llvm/llvm-project/pull/112437/files#r1802085511