Skip to content

Commit 3764d0f

Browse files
[libc][setjmp] make x86_64 longjmp naked (llvm#112581)
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
1 parent af1e9c8 commit 3764d0f

File tree

2 files changed

+33
-23
lines changed

2 files changed

+33
-23
lines changed

libc/src/setjmp/longjmp.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,22 @@
1111

1212
#include "hdr/types/jmp_buf.h"
1313
#include "src/__support/macros/config.h"
14+
#include "src/__support/macros/properties/compiler.h"
1415

1516
namespace LIBC_NAMESPACE_DECL {
1617

18+
// TODO(https://github.com/llvm/llvm-project/issues/112427)
19+
// Some of the architecture-specific definitions are marked `naked`, which in
20+
// GCC implies `nothrow`.
21+
//
22+
// Right now, our aliases aren't marked `nothrow`, so we wind up in a situation
23+
// where clang will emit -Wmissing-exception-spec if we add `nothrow` here, but
24+
// GCC will emit -Wmissing-attributes here without `nothrow`. We need to update
25+
// LLVM_LIBC_FUNCTION to denote when a function throws or not.
26+
27+
#ifdef LIBC_COMPILER_IS_GCC
28+
[[gnu::nothrow]]
29+
#endif
1730
void longjmp(jmp_buf buf, int val);
1831

1932
} // namespace LIBC_NAMESPACE_DECL

libc/src/setjmp/x86_64/longjmp.cpp

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "src/setjmp/longjmp.h"
10+
#include "include/llvm-libc-macros/offsetof-macro.h"
1011
#include "src/__support/common.h"
1112
#include "src/__support/macros/config.h"
1213

@@ -16,30 +17,26 @@
1617

1718
namespace LIBC_NAMESPACE_DECL {
1819

19-
LLVM_LIBC_FUNCTION(void, longjmp, (jmp_buf buf, int val)) {
20-
register __UINT64_TYPE__ rbx __asm__("rbx");
21-
register __UINT64_TYPE__ rbp __asm__("rbp");
22-
register __UINT64_TYPE__ r12 __asm__("r12");
23-
register __UINT64_TYPE__ r13 __asm__("r13");
24-
register __UINT64_TYPE__ r14 __asm__("r14");
25-
register __UINT64_TYPE__ r15 __asm__("r15");
26-
register __UINT64_TYPE__ rsp __asm__("rsp");
27-
register __UINT64_TYPE__ rax __asm__("rax");
20+
[[gnu::naked]]
21+
LLVM_LIBC_FUNCTION(void, longjmp, (jmp_buf, int)) {
22+
asm(R"(
23+
cmpl $0x1, %%esi
24+
adcl $0x0, %%esi
25+
movq %%rsi, %%rax
2826
29-
// ABI requires that the return value should be stored in rax. So, we store
30-
// |val| in rax. Note that this has to happen before we restore the registers
31-
// from values in |buf|. Otherwise, once rsp and rbp are updated, we cannot
32-
// read |val|.
33-
val = val == 0 ? 1 : val;
34-
LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(rax) : "m"(val) :);
35-
LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(rbx) : "m"(buf->rbx) :);
36-
LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(rbp) : "m"(buf->rbp) :);
37-
LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(r12) : "m"(buf->r12) :);
38-
LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(r13) : "m"(buf->r13) :);
39-
LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(r14) : "m"(buf->r14) :);
40-
LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(r15) : "m"(buf->r15) :);
41-
LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(rsp) : "m"(buf->rsp) :);
42-
LIBC_INLINE_ASM("jmp *%0\n\t" : : "m"(buf->rip));
27+
movq %c[rbx](%%rdi), %%rbx
28+
movq %c[rbp](%%rdi), %%rbp
29+
movq %c[r12](%%rdi), %%r12
30+
movq %c[r13](%%rdi), %%r13
31+
movq %c[r14](%%rdi), %%r14
32+
movq %c[r15](%%rdi), %%r15
33+
movq %c[rsp](%%rdi), %%rsp
34+
jmpq *%c[rip](%%rdi)
35+
)" ::[rbx] "i"(offsetof(__jmp_buf, rbx)),
36+
[rbp] "i"(offsetof(__jmp_buf, rbp)), [r12] "i"(offsetof(__jmp_buf, r12)),
37+
[r13] "i"(offsetof(__jmp_buf, r13)), [r14] "i"(offsetof(__jmp_buf, r14)),
38+
[r15] "i"(offsetof(__jmp_buf, r15)), [rsp] "i"(offsetof(__jmp_buf, rsp)),
39+
[rip] "i"(offsetof(__jmp_buf, rip)));
4340
}
4441

4542
} // namespace LIBC_NAMESPACE_DECL

0 commit comments

Comments
 (0)