[libc] implement sigsetjmp for thumb/thumb2/armv7-a (#138147)
This commit is contained in:
committed by
GitHub
parent
c79b68541b
commit
a8f460d1dc
@@ -201,6 +201,8 @@ if(LLVM_LIBC_FULL_BUILD)
|
||||
# setjmp.h entrypoints
|
||||
libc.src.setjmp.longjmp
|
||||
libc.src.setjmp.setjmp
|
||||
libc.src.setjmp.siglongjmp
|
||||
libc.src.setjmp.sigsetjmp
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
// Issue: https://github.com/llvm/llvm-project/issues/136358
|
||||
#if defined(__linux__)
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || \
|
||||
defined(__riscv)
|
||||
defined(__arm__) || defined(__riscv)
|
||||
#define __LIBC_HAS_SIGJMP_BUF
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -8,6 +8,22 @@ add_entrypoint_object(
|
||||
libc.hdr.types.jmp_buf
|
||||
)
|
||||
|
||||
if (TARGET libc.src.setjmp.sigsetjmp_epilogue)
|
||||
add_entrypoint_object(
|
||||
sigsetjmp
|
||||
SRCS
|
||||
sigsetjmp.cpp
|
||||
HDRS
|
||||
../sigsetjmp.h
|
||||
DEPENDS
|
||||
libc.hdr.types.jmp_buf
|
||||
libc.hdr.types.sigset_t
|
||||
libc.hdr.offsetof_macros
|
||||
libc.src.setjmp.sigsetjmp_epilogue
|
||||
libc.src.setjmp.setjmp
|
||||
)
|
||||
endif()
|
||||
|
||||
add_entrypoint_object(
|
||||
longjmp
|
||||
SRCS
|
||||
|
||||
65
libc/src/setjmp/arm/sigsetjmp.cpp
Normal file
65
libc/src/setjmp/arm/sigsetjmp.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
//===-- Implementation of sigsetjmp ---------------------------------------===//
|
||||
//
|
||||
// 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/sigsetjmp.h"
|
||||
#include "hdr/offsetof_macros.h"
|
||||
#include "src/__support/common.h"
|
||||
#include "src/__support/macros/config.h"
|
||||
#include "src/setjmp/setjmp_impl.h"
|
||||
#include "src/setjmp/sigsetjmp_epilogue.h"
|
||||
|
||||
namespace LIBC_NAMESPACE_DECL {
|
||||
[[gnu::naked]]
|
||||
LLVM_LIBC_FUNCTION(int, sigsetjmp, (sigjmp_buf buf)) {
|
||||
#if defined(__thumb__) && __ARM_ARCH_ISA_THUMB == 1
|
||||
// Thumb1 does not support the high registers > r7 in stmia, so move them
|
||||
// into lower GPRs first.
|
||||
asm(R"(
|
||||
tst r1, r1
|
||||
bne .Ldosave
|
||||
b %c[setjmp]
|
||||
.Ldosave:
|
||||
str r4, [r0, #%c[extra]]
|
||||
mov r4, lr
|
||||
str r4, [r0, #%c[retaddr]]
|
||||
mov r4, r0
|
||||
bl %c[setjmp]
|
||||
mov r1, r0
|
||||
mov r0, r4
|
||||
ldr r4, [r0, #%c[retaddr]]
|
||||
mov lr, r4
|
||||
ldr r4, [r0, #%c[extra]]
|
||||
b %c[epilogue]
|
||||
)" ::[retaddr] "i"(offsetof(__jmp_buf, sig_retaddr)),
|
||||
[extra] "i"(offsetof(__jmp_buf, sig_extra)), [setjmp] "i"(setjmp),
|
||||
[epilogue] "i"(sigsetjmp_epilogue)
|
||||
: "r0", "r1", "r4");
|
||||
#else
|
||||
// Some thumb2 linkers do not support conditional branch to PLT.
|
||||
// We branch to local labels instead.
|
||||
asm(R"(
|
||||
tst r1, r1
|
||||
bne .Ldosave
|
||||
b %c[setjmp]
|
||||
.Ldosave:
|
||||
str r4, [r0, #%c[extra]]
|
||||
str lr, [r0, #%c[retaddr]]
|
||||
mov r4, r0
|
||||
bl %c[setjmp]
|
||||
mov r1, r0
|
||||
mov r0, r4
|
||||
ldr lr, [r0, #%c[retaddr]]
|
||||
ldr r4, [r0, #%c[extra]]
|
||||
b %c[epilogue]
|
||||
)" ::[retaddr] "i"(offsetof(__jmp_buf, sig_retaddr)),
|
||||
[extra] "i"(offsetof(__jmp_buf, sig_extra)), [setjmp] "X"(setjmp),
|
||||
[epilogue] "X"(sigsetjmp_epilogue)
|
||||
: "r0", "r1", "r4");
|
||||
#endif
|
||||
}
|
||||
} // namespace LIBC_NAMESPACE_DECL
|
||||
Reference in New Issue
Block a user