Skip to content

Commit 42078cb

Browse files
[libc][arm] implement setjmp/longjmp
Note: our baremetal arm configuration compiles this as `--target=arm-none-eabi`, so this code is built in -marm mode. It could be smaller with `--target=armv7-none-eabi -mthumb`. The assembler is valid ARMv5, or THUMB2, but not THUMB(1). Unclear yet if we need to support THUMB(1); may depend on whether downstream users are using llvm-libc's cmake.
1 parent df626dd commit 42078cb

File tree

9 files changed

+98
-7
lines changed

9 files changed

+98
-7
lines changed

libc/config/baremetal/arm/entrypoints.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ set(TARGET_LIBC_ENTRYPOINTS
2626
# errno.h entrypoints
2727
libc.src.errno.errno
2828

29+
# setjmp.h entrypoints
30+
libc.src.setjmp.longjmp
31+
libc.src.setjmp.setjmp
32+
2933
# string.h entrypoints
3034
libc.src.string.bcmp
3135
libc.src.string.bcopy

libc/config/baremetal/arm/headers.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
set(TARGET_PUBLIC_HEADERS
22
libc.include.assert
33
libc.include.ctype
4-
libc.include.fenv
54
libc.include.errno
5+
libc.include.fenv
66
libc.include.float
7-
libc.include.stdint
87
libc.include.inttypes
98
libc.include.math
9+
libc.include.setjmp
1010
libc.include.stdfix
11+
libc.include.stdint
1112
libc.include.stdio
1213
libc.include.stdlib
1314
libc.include.string

libc/config/linux/arm/entrypoints.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ set(TARGET_LIBC_ENTRYPOINTS
2020
# errno.h entrypoints
2121
libc.src.errno.errno
2222

23+
# setjmp.h entrypoints
24+
libc.src.setjmp.longjmp
25+
libc.src.setjmp.setjmp
26+
2327
# string.h entrypoints
2428
libc.src.string.bcmp
2529
libc.src.string.bcopy

libc/config/linux/arm/headers.txt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
set(TARGET_PUBLIC_HEADERS
22
libc.include.ctype
3-
libc.include.fenv
43
libc.include.errno
4+
libc.include.fenv
55
libc.include.float
6-
libc.include.stdint
76
libc.include.inttypes
87
libc.include.math
9-
libc.include.stdckdint
8+
libc.include.search
9+
libc.include.setjmp
1010
libc.include.stdbit
11+
libc.include.stdckdint
12+
libc.include.stdint
1113
libc.include.stdlib
1214
libc.include.string
1315
libc.include.strings
14-
libc.include.search
15-
libc.include.wchar
1616
libc.include.uchar
17+
libc.include.wchar
1718

1819
# Disabled due to epoll_wait syscalls not being available on this platform.
1920
# libc.include.sys_epoll

libc/include/llvm-libc-types/jmp_buf.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ typedef struct {
3232
#elif defined(__riscv_float_abi_single)
3333
#error "__jmp_buf not available for your target architecture."
3434
#endif
35+
#elif defined(__arm__)
36+
// r4, r5, r6, r7, r8, r9, r10, r11, r12, lr
37+
long opaque [10];
3538
#else
3639
#error "__jmp_buf not available for your target architecture."
3740
#endif

libc/include/setjmp.h.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define LLVM_LIBC_SETJMP_H
1111

1212
#include "__llvm-libc-common.h"
13+
#include "llvm-libc-types/jmp_buf.h"
1314

1415
%%public_api()
1516

libc/src/setjmp/arm/CMakeLists.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
add_entrypoint_object(
2+
setjmp
3+
SRCS
4+
setjmp.cpp
5+
HDRS
6+
../setjmp_impl.h
7+
DEPENDS
8+
libc.include.setjmp
9+
)
10+
11+
add_entrypoint_object(
12+
longjmp
13+
SRCS
14+
longjmp.cpp
15+
HDRS
16+
../longjmp.h
17+
DEPENDS
18+
libc.include.setjmp
19+
)

libc/src/setjmp/arm/longjmp.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
//===-- Implementation of longjmp -----------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#include "src/setjmp/longjmp.h"
11+
#include "src/__support/common.h"
12+
#include "src/__support/macros/properties/architectures.h"
13+
14+
#if !defined(LIBC_TARGET_ARCH_IS_ARM)
15+
#error "Invalid file include"
16+
#endif
17+
18+
namespace LIBC_NAMESPACE {
19+
20+
[[gnu::naked]]
21+
LLVM_LIBC_FUNCTION(void, longjmp, (__jmp_buf * buf, int val)) {
22+
asm("ldm.w r0!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}\n\t"
23+
"mov sp, r12\n\t"
24+
"movs r0, r1\n\t"
25+
"it eq\n\t"
26+
"moveq r0, 1\n\t"
27+
"bx lr"
28+
);
29+
}
30+
31+
} // namespace LIBC_NAMESPACE

libc/src/setjmp/arm/setjmp.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//===-- Implementation of 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+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/__support/common.h"
10+
#include "src/setjmp/setjmp_impl.h"
11+
12+
#if !defined(LIBC_TARGET_ARCH_IS_ARM)
13+
#error "Invalid file include"
14+
#endif
15+
16+
namespace LIBC_NAMESPACE {
17+
18+
[[gnu::naked]]
19+
LLVM_LIBC_FUNCTION(int, setjmp, (__jmp_buf * buf)) {
20+
asm("mov r12, sp\n\t"
21+
"stm.w r0!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}\n\t"
22+
"mov.w r0, 0\n\t"
23+
"bx lr\n\t"
24+
);
25+
}
26+
27+
} // namespace LIBC_NAMESPACE

0 commit comments

Comments
 (0)