-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[libc][arm] implement a basic setjmp/longjmp #93220
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
Changes from all commits
42078cb
cbe594f
7738433
96d8f14
51464ea
2d13bf8
23a3943
16619b2
349e874
1e28ecb
6bed9ef
7e7afe4
0406a75
5dac500
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
add_entrypoint_object( | ||
setjmp | ||
SRCS | ||
setjmp.cpp | ||
HDRS | ||
../setjmp_impl.h | ||
DEPENDS | ||
libc.include.setjmp | ||
) | ||
|
||
add_entrypoint_object( | ||
longjmp | ||
SRCS | ||
longjmp.cpp | ||
HDRS | ||
../longjmp.h | ||
DEPENDS | ||
libc.include.setjmp | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
|
||
//===-- Implementation of longjmp -----------------------------------------===// | ||
// | ||
// 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/longjmp.h" | ||
#include "src/__support/common.h" | ||
|
||
namespace LIBC_NAMESPACE { | ||
|
||
#if defined(__thumb__) && __ARM_ARCH_ISA_THUMB == 1 | ||
|
||
[[gnu::naked, gnu::target("thumb")]] | ||
LLVM_LIBC_FUNCTION(void, longjmp, (__jmp_buf * buf, int val)) { | ||
asm(R"( | ||
# Reload r4, r5, r6, r7. | ||
ldmia r0!, {r4-r7} | ||
|
||
# Reload r8, r9. They cannot appear in register lists so load them | ||
# into the lower registers, then move them into place. | ||
ldmia r0!, {r2-r3} | ||
mov r8, r2 | ||
mov r9, r3 | ||
|
||
# Reload r10, r11. They cannot appear in register lists so load them | ||
# into the lower registers, then move them into place. | ||
ldmia r0!, {r2-r3} | ||
mov r10, r2 | ||
mov r11, r3 | ||
|
||
# Reload sp, lr. They cannot appear in register lists so load them | ||
# into the lower registers, then move them into place. | ||
ldmia r0!, {r2-r3} | ||
mov sp, r2 | ||
mov lr, r3 | ||
|
||
# return val ?: 1; | ||
movs r0, r1 | ||
bne .Lret_val | ||
movs r0, #1 | ||
|
||
.Lret_val: | ||
bx lr)"); | ||
} | ||
|
||
#else // Thumb2 or ARM | ||
|
||
// TODO(https://github.com/llvm/llvm-project/issues/94061): fp registers | ||
// (d0-d16) | ||
// TODO(https://github.com/llvm/llvm-project/issues/94062): pac+bti | ||
[[gnu::naked]] | ||
LLVM_LIBC_FUNCTION(void, longjmp, (__jmp_buf * buf, int val)) { | ||
asm(R"( | ||
# While sp may appear in a register list for ARM mode, it may not for | ||
# Thumb2 mode. Just load the previous value of sp into r12 then move it | ||
# into sp, so that this code is portable between ARM and Thumb2. | ||
|
||
ldm r0, {r4-r12, lr} | ||
nickdesaulniers marked this conversation as resolved.
Show resolved
Hide resolved
|
||
mov sp, r12 | ||
|
||
# return val ?: 1; | ||
movs r0, r1 | ||
it eq | ||
moveq r0, #1 | ||
bx lr)"); | ||
} | ||
|
||
#endif | ||
|
||
} // namespace LIBC_NAMESPACE |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
//===-- Implementation of setjmp ------------------------------------------===// | ||
// | ||
// 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/__support/common.h" | ||
#include "src/setjmp/setjmp_impl.h" | ||
|
||
namespace LIBC_NAMESPACE { | ||
|
||
#if defined(__thumb__) && __ARM_ARCH_ISA_THUMB == 1 | ||
|
||
[[gnu::naked, gnu::target("thumb")]] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just curious, does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If multi-versioned symbols is referring to function multi-versioning then there is a beta version defined in https://arm-software.github.io/acle/main/acle.html#function-multi-versioning AFAIK it has been concentrating on AArch64 though. Unlikely to be used in bare-metal cases like cortex-m0 though. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, depends on loader support, which we currently lack. Also, not sure yet we want to support a libc with mixed arm/thumb mode support. Frankly, I'd suspect that folks that care about libc support on 32b ARM only really care about Thumb mode (1 or 2) (unless they're running on some variant with only ARM mode support). |
||
LLVM_LIBC_FUNCTION(int, setjmp, (__jmp_buf * buf)) { | ||
asm(R"( | ||
# Store r4, r5, r6, and r7 into buf. | ||
stmia r0!, {r4-r7} | ||
|
||
# Store r8, r9, r10, r11, sp, and lr into buf. Thumb(1) doesn't support | ||
# the high registers > r7 in stmia, so move them into lower GPRs first. | ||
# Thumb(1) also doesn't support using str with sp or lr, move them | ||
# together with the rest. | ||
mov r1, r8 | ||
mov r2, r9 | ||
mov r3, r10 | ||
stmia r0!, {r1-r3} | ||
|
||
mov r1, r11 | ||
mov r2, sp | ||
mov r3, lr | ||
stmia r0!, {r1-r3} | ||
|
||
# Return 0. | ||
movs r0, #0 | ||
bx lr)"); | ||
} | ||
|
||
#else // Thumb2 or ARM | ||
|
||
// TODO(https://github.com/llvm/llvm-project/issues/94061): fp registers | ||
// (d0-d16) | ||
// TODO(https://github.com/llvm/llvm-project/issues/94062): pac+bti | ||
[[gnu::naked]] | ||
LLVM_LIBC_FUNCTION(int, setjmp, (__jmp_buf * buf)) { | ||
asm(R"( | ||
# While sp may appear in a register list for ARM mode, it may not for | ||
# Thumb2 mode. Just move it into r12 then stm that, so that this code | ||
# is portable between ARM and Thumb2. | ||
mov r12, sp | ||
nickdesaulniers marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
# Store r4, r5, r6, r7, r8, r9, r10, r11, sp, and lr into buf. | ||
stm r0, {r4-r12, lr} | ||
|
||
# Return zero. | ||
mov r0, #0 | ||
bx lr)"); | ||
} | ||
|
||
#endif | ||
|
||
} // namespace LIBC_NAMESPACE |
Uh oh!
There was an error while loading. Please reload this page.