|
6 | 6 | //
|
7 | 7 | //===----------------------------------------------------------------------===//
|
8 | 8 |
|
| 9 | +#include "include/llvm-libc-macros/offsetof-macro.h" |
9 | 10 | #include "src/__support/common.h"
|
10 | 11 | #include "src/__support/macros/config.h"
|
11 | 12 | #include "src/setjmp/setjmp_impl.h"
|
|
16 | 17 |
|
17 | 18 | namespace LIBC_NAMESPACE_DECL {
|
18 | 19 |
|
19 |
| -LLVM_LIBC_FUNCTION(int, setjmp, (jmp_buf buf)) { |
20 |
| - register __UINT64_TYPE__ rbx __asm__("rbx"); |
21 |
| - register __UINT64_TYPE__ r12 __asm__("r12"); |
22 |
| - register __UINT64_TYPE__ r13 __asm__("r13"); |
23 |
| - register __UINT64_TYPE__ r14 __asm__("r14"); |
24 |
| - register __UINT64_TYPE__ r15 __asm__("r15"); |
25 |
| - |
26 |
| - // We want to store the register values as is. So, we will suppress the |
27 |
| - // compiler warnings about the uninitialized variables declared above. |
28 |
| -#pragma GCC diagnostic push |
29 |
| -#pragma GCC diagnostic ignored "-Wuninitialized" |
30 |
| - LIBC_INLINE_ASM("mov %1, %0\n\t" : "=m"(buf->rbx) : "r"(rbx) :); |
31 |
| - LIBC_INLINE_ASM("mov %1, %0\n\t" : "=m"(buf->r12) : "r"(r12) :); |
32 |
| - LIBC_INLINE_ASM("mov %1, %0\n\t" : "=m"(buf->r13) : "r"(r13) :); |
33 |
| - LIBC_INLINE_ASM("mov %1, %0\n\t" : "=m"(buf->r14) : "r"(r14) :); |
34 |
| - LIBC_INLINE_ASM("mov %1, %0\n\t" : "=m"(buf->r15) : "r"(r15) :); |
35 |
| -#pragma GCC diagnostic pop |
36 |
| - |
37 |
| - // We want the rbp of the caller, which is what __builtin_frame_address(1) |
38 |
| - // should return. But, compilers generate a warning that calling |
39 |
| - // __builtin_frame_address with non-zero argument is unsafe. So, we use |
40 |
| - // the knowledge of the x86_64 ABI to fetch the callers rbp. As per the ABI, |
41 |
| - // the rbp of the caller is pushed on to the stack and then new top is saved |
42 |
| - // in this function's rbp. So, we fetch it from location at which this |
43 |
| - // functions's rbp is pointing. |
44 |
| - buf->rbp = *reinterpret_cast<__UINTPTR_TYPE__ *>(__builtin_frame_address(0)); |
45 |
| - |
46 |
| - // The callers stack address is exactly 2 pointer widths ahead of the current |
47 |
| - // frame pointer - between the current frame pointer and the rsp of the caller |
48 |
| - // are the return address (pushed by the x86_64 call instruction) and the |
49 |
| - // previous stack pointer as required by the x86_64 ABI. |
50 |
| - // The stack pointer is ahead because the stack grows down on x86_64. |
51 |
| - buf->rsp = reinterpret_cast<__UINTPTR_TYPE__>(__builtin_frame_address(0)) + |
52 |
| - sizeof(__UINTPTR_TYPE__) * 2; |
53 |
| - buf->rip = reinterpret_cast<__UINTPTR_TYPE__>(__builtin_return_address(0)); |
54 |
| - return 0; |
| 20 | +[[gnu::naked]] |
| 21 | +LLVM_LIBC_FUNCTION(int, setjmp, (__jmp_buf * buf)) { |
| 22 | + asm(R"( |
| 23 | + mov %%rbx, %c[rbx](%%rdi) |
| 24 | + mov %%rbp, %c[rbp](%%rdi) |
| 25 | + mov %%r12, %c[r12](%%rdi) |
| 26 | + mov %%r13, %c[r13](%%rdi) |
| 27 | + mov %%r14, %c[r14](%%rdi) |
| 28 | + mov %%r15, %c[r15](%%rdi) |
| 29 | +
|
| 30 | + lea 8(%%rsp), %%rax |
| 31 | + mov %%rax, %c[rsp](%%rdi) |
| 32 | +
|
| 33 | + mov (%%rsp), %%rax |
| 34 | + mov %%rax, %c[rip](%%rdi) |
| 35 | +
|
| 36 | + xorl %%eax, %%eax |
| 37 | + retq)" ::[rbx] "i"(offsetof(__jmp_buf, rbx)), |
| 38 | + [rbp] "i"(offsetof(__jmp_buf, rbp)), [r12] "i"(offsetof(__jmp_buf, r12)), |
| 39 | + [r13] "i"(offsetof(__jmp_buf, r13)), [r14] "i"(offsetof(__jmp_buf, r14)), |
| 40 | + [r15] "i"(offsetof(__jmp_buf, r15)), [rsp] "i"(offsetof(__jmp_buf, rsp)), |
| 41 | + [rip] "i"(offsetof(__jmp_buf, rip)) |
| 42 | + : "rax"); |
55 | 43 | }
|
56 | 44 |
|
57 | 45 | } // namespace LIBC_NAMESPACE_DECL
|
0 commit comments