diff options
author | Nick Desaulniers (paternity leave) <nickdesaulniers@users.noreply.github.com> | 2024-06-25 09:58:50 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-25 09:58:50 -0700 |
commit | 4c87212d63c3b45e9371434239553ef007216106 (patch) | |
tree | 006f9a23b1563cb5652be4375c7938965363dcbd | |
parent | 0b049ce64653a8cbdeedaa2bfe6cc79fc6af5d40 (diff) | |
download | llvm-4c87212d63c3b45e9371434239553ef007216106.zip llvm-4c87212d63c3b45e9371434239553ef007216106.tar.gz llvm-4c87212d63c3b45e9371434239553ef007216106.tar.bz2 |
[libc][thumb] support syscalls from thumb mode (#96558)
r7 is reserved in thumb2 (typically for the frame pointer, as opposed to r11 in
ARM mode), so assigning to a variable with explicit register storage in r7 will
produce an error.
But r7 is where the Linux kernel expects the syscall number to be placed. We
can use a temporary to get the register allocator to pick a temporary, which we
save+restore the previous value of r7 in.
Fixes: #93738
-rw-r--r-- | libc/src/__support/OSUtil/linux/arm/syscall.h | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/libc/src/__support/OSUtil/linux/arm/syscall.h b/libc/src/__support/OSUtil/linux/arm/syscall.h index af10074..9674ee4 100644 --- a/libc/src/__support/OSUtil/linux/arm/syscall.h +++ b/libc/src/__support/OSUtil/linux/arm/syscall.h @@ -12,14 +12,29 @@ #include "src/__support/common.h" #ifdef __thumb__ -#error "The arm syscall implementation does not yet support thumb flavor." -#endif // __thumb__ +#define R7 long r7 = number +#define SYSCALL_INSTR(input_constraint) \ + int temp; \ + LIBC_INLINE_ASM(R"( + mov %[temp], r7 + mov r7, %2 + svc #0 + mov r7, %[temp] + )" \ + : "=r"(r0), [temp] "=&r"(temp) \ + : input_constraint \ + : "memory", "cc") +#else +#define R7 register long r7 asm("r7") = number +#define SYSCALL_INSTR(input_constraint) \ + LIBC_INLINE_ASM("svc 0" : "=r"(r0) : input_constraint : "memory", "cc") +#endif #define REGISTER_DECL_0 \ - register long r7 __asm__("r7") = number; \ + R7; \ register long r0 __asm__("r0"); #define REGISTER_DECL_1 \ - register long r7 __asm__("r7") = number; \ + R7; \ register long r0 __asm__("r0") = arg1; #define REGISTER_DECL_2 \ REGISTER_DECL_1 \ @@ -45,9 +60,6 @@ #define REGISTER_CONSTRAINT_5 REGISTER_CONSTRAINT_4, "r"(r4) #define REGISTER_CONSTRAINT_6 REGISTER_CONSTRAINT_5, "r"(r5) -#define SYSCALL_INSTR(input_constraint) \ - LIBC_INLINE_ASM("svc 0" : "=r"(r0) : input_constraint : "memory", "cc") - namespace LIBC_NAMESPACE { LIBC_INLINE long syscall_impl(long number) { |