[libc-commits] [libc] [libc][arm] implement setjmp/longjmp (PR #93220)
Nick Desaulniers via libc-commits
libc-commits at lists.llvm.org
Thu May 23 11:05:13 PDT 2024
https://github.com/nickdesaulniers updated https://github.com/llvm/llvm-project/pull/93220
>From 42078cb53551478adac1b0b0d2ca4dccedd87401 Mon Sep 17 00:00:00 2001
From: Nick Desaulniers <ndesaulniers at google.com>
Date: Thu, 23 May 2024 10:29:09 -0700
Subject: [PATCH 1/4] [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.
---
libc/config/baremetal/arm/entrypoints.txt | 4 +++
libc/config/baremetal/arm/headers.txt | 5 ++--
libc/config/linux/arm/entrypoints.txt | 4 +++
libc/config/linux/arm/headers.txt | 11 ++++----
libc/include/llvm-libc-types/jmp_buf.h | 3 +++
libc/include/setjmp.h.def | 1 +
libc/src/setjmp/arm/CMakeLists.txt | 19 ++++++++++++++
libc/src/setjmp/arm/longjmp.cpp | 31 +++++++++++++++++++++++
libc/src/setjmp/arm/setjmp.cpp | 27 ++++++++++++++++++++
9 files changed, 98 insertions(+), 7 deletions(-)
create mode 100644 libc/src/setjmp/arm/CMakeLists.txt
create mode 100644 libc/src/setjmp/arm/longjmp.cpp
create mode 100644 libc/src/setjmp/arm/setjmp.cpp
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index 4e3d1cb9f5337..ff192edfffe3d 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -26,6 +26,10 @@ set(TARGET_LIBC_ENTRYPOINTS
# errno.h entrypoints
libc.src.errno.errno
+ # setjmp.h entrypoints
+ libc.src.setjmp.longjmp
+ libc.src.setjmp.setjmp
+
# string.h entrypoints
libc.src.string.bcmp
libc.src.string.bcopy
diff --git a/libc/config/baremetal/arm/headers.txt b/libc/config/baremetal/arm/headers.txt
index 3608364e45bde..28fd1ce9128d2 100644
--- a/libc/config/baremetal/arm/headers.txt
+++ b/libc/config/baremetal/arm/headers.txt
@@ -1,13 +1,14 @@
set(TARGET_PUBLIC_HEADERS
libc.include.assert
libc.include.ctype
- libc.include.fenv
libc.include.errno
+ libc.include.fenv
libc.include.float
- libc.include.stdint
libc.include.inttypes
libc.include.math
+ libc.include.setjmp
libc.include.stdfix
+ libc.include.stdint
libc.include.stdio
libc.include.stdlib
libc.include.string
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index 335981ff7dc7c..af824d294d7d7 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -20,6 +20,10 @@ set(TARGET_LIBC_ENTRYPOINTS
# errno.h entrypoints
libc.src.errno.errno
+ # setjmp.h entrypoints
+ libc.src.setjmp.longjmp
+ libc.src.setjmp.setjmp
+
# string.h entrypoints
libc.src.string.bcmp
libc.src.string.bcopy
diff --git a/libc/config/linux/arm/headers.txt b/libc/config/linux/arm/headers.txt
index 1180564fe458c..84078a947031a 100644
--- a/libc/config/linux/arm/headers.txt
+++ b/libc/config/linux/arm/headers.txt
@@ -1,19 +1,20 @@
set(TARGET_PUBLIC_HEADERS
libc.include.ctype
- libc.include.fenv
libc.include.errno
+ libc.include.fenv
libc.include.float
- libc.include.stdint
libc.include.inttypes
libc.include.math
- libc.include.stdckdint
+ libc.include.search
+ libc.include.setjmp
libc.include.stdbit
+ libc.include.stdckdint
+ libc.include.stdint
libc.include.stdlib
libc.include.string
libc.include.strings
- libc.include.search
- libc.include.wchar
libc.include.uchar
+ libc.include.wchar
# Disabled due to epoll_wait syscalls not being available on this platform.
# libc.include.sys_epoll
diff --git a/libc/include/llvm-libc-types/jmp_buf.h b/libc/include/llvm-libc-types/jmp_buf.h
index 29a1df9ad6823..a5379336865de 100644
--- a/libc/include/llvm-libc-types/jmp_buf.h
+++ b/libc/include/llvm-libc-types/jmp_buf.h
@@ -32,6 +32,9 @@ typedef struct {
#elif defined(__riscv_float_abi_single)
#error "__jmp_buf not available for your target architecture."
#endif
+#elif defined(__arm__)
+ // r4, r5, r6, r7, r8, r9, r10, r11, r12, lr
+ long opaque [10];
#else
#error "__jmp_buf not available for your target architecture."
#endif
diff --git a/libc/include/setjmp.h.def b/libc/include/setjmp.h.def
index 670bc1ac0fe24..cb083b8cd023e 100644
--- a/libc/include/setjmp.h.def
+++ b/libc/include/setjmp.h.def
@@ -10,6 +10,7 @@
#define LLVM_LIBC_SETJMP_H
#include "__llvm-libc-common.h"
+#include "llvm-libc-types/jmp_buf.h"
%%public_api()
diff --git a/libc/src/setjmp/arm/CMakeLists.txt b/libc/src/setjmp/arm/CMakeLists.txt
new file mode 100644
index 0000000000000..da97b79c9fea0
--- /dev/null
+++ b/libc/src/setjmp/arm/CMakeLists.txt
@@ -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
+)
diff --git a/libc/src/setjmp/arm/longjmp.cpp b/libc/src/setjmp/arm/longjmp.cpp
new file mode 100644
index 0000000000000..752318edfa580
--- /dev/null
+++ b/libc/src/setjmp/arm/longjmp.cpp
@@ -0,0 +1,31 @@
+
+//===-- 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"
+#include "src/__support/macros/properties/architectures.h"
+
+#if !defined(LIBC_TARGET_ARCH_IS_ARM)
+#error "Invalid file include"
+#endif
+
+namespace LIBC_NAMESPACE {
+
+[[gnu::naked]]
+LLVM_LIBC_FUNCTION(void, longjmp, (__jmp_buf * buf, int val)) {
+ asm("ldm.w r0!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}\n\t"
+ "mov sp, r12\n\t"
+ "movs r0, r1\n\t"
+ "it eq\n\t"
+ "moveq r0, 1\n\t"
+ "bx lr"
+ );
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/setjmp/arm/setjmp.cpp b/libc/src/setjmp/arm/setjmp.cpp
new file mode 100644
index 0000000000000..9304ff6b47050
--- /dev/null
+++ b/libc/src/setjmp/arm/setjmp.cpp
@@ -0,0 +1,27 @@
+//===-- 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"
+
+#if !defined(LIBC_TARGET_ARCH_IS_ARM)
+#error "Invalid file include"
+#endif
+
+namespace LIBC_NAMESPACE {
+
+[[gnu::naked]]
+LLVM_LIBC_FUNCTION(int, setjmp, (__jmp_buf * buf)) {
+ asm("mov r12, sp\n\t"
+ "stm.w r0!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}\n\t"
+ "mov.w r0, 0\n\t"
+ "bx lr\n\t"
+ );
+}
+
+} // namespace LIBC_NAMESPACE
>From cbe594f7439d1b85ec85da1b32a3a2da25dc923f Mon Sep 17 00:00:00 2001
From: Nick Desaulniers <ndesaulniers at google.com>
Date: Thu, 23 May 2024 10:40:44 -0700
Subject: [PATCH 2/4] format
---
libc/include/llvm-libc-types/jmp_buf.h | 2 +-
libc/src/setjmp/arm/longjmp.cpp | 3 +--
libc/src/setjmp/arm/setjmp.cpp | 3 +--
3 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/libc/include/llvm-libc-types/jmp_buf.h b/libc/include/llvm-libc-types/jmp_buf.h
index a5379336865de..8949be9fa0ab7 100644
--- a/libc/include/llvm-libc-types/jmp_buf.h
+++ b/libc/include/llvm-libc-types/jmp_buf.h
@@ -34,7 +34,7 @@ typedef struct {
#endif
#elif defined(__arm__)
// r4, r5, r6, r7, r8, r9, r10, r11, r12, lr
- long opaque [10];
+ long opaque[10];
#else
#error "__jmp_buf not available for your target architecture."
#endif
diff --git a/libc/src/setjmp/arm/longjmp.cpp b/libc/src/setjmp/arm/longjmp.cpp
index 752318edfa580..edf605c0de544 100644
--- a/libc/src/setjmp/arm/longjmp.cpp
+++ b/libc/src/setjmp/arm/longjmp.cpp
@@ -24,8 +24,7 @@ LLVM_LIBC_FUNCTION(void, longjmp, (__jmp_buf * buf, int val)) {
"movs r0, r1\n\t"
"it eq\n\t"
"moveq r0, 1\n\t"
- "bx lr"
- );
+ "bx lr");
}
} // namespace LIBC_NAMESPACE
diff --git a/libc/src/setjmp/arm/setjmp.cpp b/libc/src/setjmp/arm/setjmp.cpp
index 9304ff6b47050..52ceeee3c4237 100644
--- a/libc/src/setjmp/arm/setjmp.cpp
+++ b/libc/src/setjmp/arm/setjmp.cpp
@@ -20,8 +20,7 @@ LLVM_LIBC_FUNCTION(int, setjmp, (__jmp_buf * buf)) {
asm("mov r12, sp\n\t"
"stm.w r0!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}\n\t"
"mov.w r0, 0\n\t"
- "bx lr\n\t"
- );
+ "bx lr");
}
} // namespace LIBC_NAMESPACE
>From 77384336fb4ef69a615b59fc0152ffdc74a4fb4e Mon Sep 17 00:00:00 2001
From: Nick Desaulniers <ndesaulniers at google.com>
Date: Thu, 23 May 2024 10:43:25 -0700
Subject: [PATCH 3/4] remove useless preprocessor warnings
---
libc/src/setjmp/arm/longjmp.cpp | 5 -----
libc/src/setjmp/arm/setjmp.cpp | 4 ----
2 files changed, 9 deletions(-)
diff --git a/libc/src/setjmp/arm/longjmp.cpp b/libc/src/setjmp/arm/longjmp.cpp
index edf605c0de544..e496af8394490 100644
--- a/libc/src/setjmp/arm/longjmp.cpp
+++ b/libc/src/setjmp/arm/longjmp.cpp
@@ -9,11 +9,6 @@
#include "src/setjmp/longjmp.h"
#include "src/__support/common.h"
-#include "src/__support/macros/properties/architectures.h"
-
-#if !defined(LIBC_TARGET_ARCH_IS_ARM)
-#error "Invalid file include"
-#endif
namespace LIBC_NAMESPACE {
diff --git a/libc/src/setjmp/arm/setjmp.cpp b/libc/src/setjmp/arm/setjmp.cpp
index 52ceeee3c4237..a5f0110ad2b17 100644
--- a/libc/src/setjmp/arm/setjmp.cpp
+++ b/libc/src/setjmp/arm/setjmp.cpp
@@ -9,10 +9,6 @@
#include "src/__support/common.h"
#include "src/setjmp/setjmp_impl.h"
-#if !defined(LIBC_TARGET_ARCH_IS_ARM)
-#error "Invalid file include"
-#endif
-
namespace LIBC_NAMESPACE {
[[gnu::naked]]
>From 96d8f14ca1e83bc6af942a70b5a30fd410a67266 Mon Sep 17 00:00:00 2001
From: Nick Desaulniers <ndesaulniers at google.com>
Date: Thu, 23 May 2024 11:04:07 -0700
Subject: [PATCH 4/4] raw string literals
---
libc/src/setjmp/arm/longjmp.cpp | 13 +++++++------
libc/src/setjmp/arm/setjmp.cpp | 9 +++++----
2 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/libc/src/setjmp/arm/longjmp.cpp b/libc/src/setjmp/arm/longjmp.cpp
index e496af8394490..e5e3b28468a67 100644
--- a/libc/src/setjmp/arm/longjmp.cpp
+++ b/libc/src/setjmp/arm/longjmp.cpp
@@ -14,12 +14,13 @@ namespace LIBC_NAMESPACE {
[[gnu::naked]]
LLVM_LIBC_FUNCTION(void, longjmp, (__jmp_buf * buf, int val)) {
- asm("ldm.w r0!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}\n\t"
- "mov sp, r12\n\t"
- "movs r0, r1\n\t"
- "it eq\n\t"
- "moveq r0, 1\n\t"
- "bx lr");
+ asm(R"(
+ ldm r0, {r4-r12, lr}
+ mov sp, r12
+ movs r0, r1
+ it eq
+ moveq r0, #1
+ bx lr)");
}
} // namespace LIBC_NAMESPACE
diff --git a/libc/src/setjmp/arm/setjmp.cpp b/libc/src/setjmp/arm/setjmp.cpp
index a5f0110ad2b17..4618416146ba3 100644
--- a/libc/src/setjmp/arm/setjmp.cpp
+++ b/libc/src/setjmp/arm/setjmp.cpp
@@ -13,10 +13,11 @@ namespace LIBC_NAMESPACE {
[[gnu::naked]]
LLVM_LIBC_FUNCTION(int, setjmp, (__jmp_buf * buf)) {
- asm("mov r12, sp\n\t"
- "stm.w r0!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}\n\t"
- "mov.w r0, 0\n\t"
- "bx lr");
+ asm(R"(
+ mov r12, sp
+ stm r0, {r4-r12, lr}
+ mov r0, #0
+ bx lr)");
}
} // namespace LIBC_NAMESPACE
More information about the libc-commits
mailing list