Skip to content

Commit a449c60

Browse files
[libc][setjmp][x86] implement setjmp in terms of out of line asm
This fixes libc_setjmp_unittests for me. This would consistently fail for me locally, to the point where I could not run ninja libc-unit-tests without ninja libc_setjmp_unittests failing. Turns out that since I enabled -ftrivial-auto-var-init=pattern in commit 1d5c16d ("[libc] default enable -ftrivial-auto-var-init=pattern (llvm#78776)") this has been a problem. Our x86_64 setjmp definition disabled -Wuninitialized, so we wound up clobbering these registers and instead backing up 0xAAAAAAAAAAAAAAAA rather than the actual register value. Adding out of line asm to llvm-libc is opening pandora's box. This should not be merged without discussion and buy in from maintainers. We should have a policy in place for _when_ it's acceptable to use out of line asm or not. Link: llvm#87837 Link: llvm#88054 Link: https://discourse.llvm.org/t/hand-written-in-assembly-in-libc-setjmp-longjmp/73249
1 parent e127997 commit a449c60

File tree

5 files changed

+91
-62
lines changed

5 files changed

+91
-62
lines changed

libc/src/setjmp/x86_64/CMakeLists.txt

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
add_entrypoint_object(
22
setjmp
33
SRCS
4-
setjmp.cpp
4+
setjmp.S
55
HDRS
66
../setjmp_impl.h
7-
DEPENDS
8-
libc.include.setjmp
9-
COMPILE_OPTIONS
10-
-O3
11-
-fno-omit-frame-pointer
127
)
138

149
add_entrypoint_object(

libc/src/setjmp/x86_64/setjmp.S

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//===-- Implementation of setjmp --------------------------------*- ASM -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#define paste(ns) _ZN22 ## ns ## 6setjmpEP9__jmp_buf
10+
#define expand(x) paste(x)
11+
#define LIBC_NAMESPACE_setjump expand(LIBC_NAMESPACE)
12+
// aka _ZN22__llvm_libc_19_0_0_git6setjmpEP9__jmp_buf
13+
// aka __llvm_libc_19_0_0_git::setjmp(__jmp_buf*)
14+
15+
// Brittle! Changing the layout of __jmp_buf will break this!
16+
#define RBX_OFFSET 0
17+
#define RBP_OFFSET 8
18+
#define R12_OFFSET 16
19+
#define R13_OFFSET 24
20+
#define R14_OFFSET 32
21+
#define R15_OFFSET 40
22+
#define RSP_OFFSET 48
23+
#define RIP_OFFSET 56
24+
25+
.global setjump
26+
.global LIBC_NAMESPACE_setjump
27+
28+
.type setjump, @function
29+
.type LIBC_NAMESPACE_setjump, @function
30+
31+
setjump:
32+
LIBC_NAMESPACE_setjump:
33+
34+
mov %rbx, RBX_OFFSET(%rdi)
35+
mov %rbp, RBP_OFFSET(%rdi)
36+
mov %r12, R12_OFFSET(%rdi)
37+
mov %r13, R13_OFFSET(%rdi)
38+
mov %r14, R14_OFFSET(%rdi)
39+
mov %r15, R15_OFFSET(%rdi)
40+
lea 8(%rsp), %rax
41+
mov %rax, RSP_OFFSET(%rdi)
42+
mov (%rsp), %rax
43+
mov %rax, RIP_OFFSET(%rdi)
44+
xor %eax, %eax
45+
ret
46+
47+
.size setjump, . - setjump
48+
.size LIBC_NAMESPACE_setjump, . - LIBC_NAMESPACE_setjump
49+
50+
.section .note.GNU-stack, "", @progbits

libc/src/setjmp/x86_64/setjmp.cpp

Lines changed: 0 additions & 56 deletions
This file was deleted.

libc/test/include/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,14 @@ add_libc_test(
6969
DEPENDS
7070
libc.include.llvm-libc-macros.stdckdint_macros
7171
)
72+
73+
add_libc_test(
74+
setjmp_test
75+
SUITE
76+
libc_include_tests
77+
SRCS
78+
setjmp_test.cpp
79+
DEPENDS
80+
libc.include.llvm-libc-macros.offsetof_macro
81+
libc.include.llvm-libc-types.jmp_buf
82+
)

libc/test/include/setjmp_test.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//===-- Unittests for setjmp ----------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDSList-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "include/llvm-libc-macros/offsetof-macro.h"
10+
#include "include/llvm-libc-types/jmp_buf.h"
11+
#include "test/UnitTest/Test.h"
12+
13+
// If this test fails, then *_OFFSET macro definitions in
14+
// libc/src/setjmp/x86_64/setjmp.S need to be fixed. This is a simple change
15+
// detector.
16+
TEST(LlvmLibcSetjmpTest, JmpBufLayout) {
17+
#ifdef __x86_64__
18+
ASSERT_EQ(offsetof(__jmp_buf, rbx), 0UL);
19+
ASSERT_EQ(offsetof(__jmp_buf, rbp), 8UL);
20+
ASSERT_EQ(offsetof(__jmp_buf, r12), 16UL);
21+
ASSERT_EQ(offsetof(__jmp_buf, r13), 24UL);
22+
ASSERT_EQ(offsetof(__jmp_buf, r14), 32UL);
23+
ASSERT_EQ(offsetof(__jmp_buf, r15), 40UL);
24+
ASSERT_EQ(offsetof(__jmp_buf, rsp), 48UL);
25+
ASSERT_EQ(offsetof(__jmp_buf, rip), 56UL);
26+
ASSERT_EQ(sizeof(__jmp_buf), 64UL);
27+
ASSERT_EQ(alignof(__jmp_buf), 8UL);
28+
#endif // __x86_64__
29+
}

0 commit comments

Comments
 (0)