diff --git a/clang/docs/tools/clang-formatted-files.txt b/clang/docs/tools/clang-formatted-files.txt --- a/clang/docs/tools/clang-formatted-files.txt +++ b/clang/docs/tools/clang-formatted-files.txt @@ -2594,6 +2594,7 @@ libc/include/llvm-libc-types/FILE.h libc/include/llvm-libc-types/float_t.h libc/include/llvm-libc-types/imaxdiv_t.h +libc/include/llvm-libc-types/jmp_buf.h libc/include/llvm-libc-types/ldiv_t.h libc/include/llvm-libc-types/lldiv_t.h libc/include/llvm-libc-types/mode_t.h diff --git a/libc/config/linux/riscv64/entrypoints.txt b/libc/config/linux/riscv64/entrypoints.txt --- a/libc/config/linux/riscv64/entrypoints.txt +++ b/libc/config/linux/riscv64/entrypoints.txt @@ -371,6 +371,10 @@ # sched.h entrypoints libc.src.sched.__sched_getcpucount + # setjmp.h entrypoints + libc.src.setjmp.longjmp + libc.src.setjmp.setjmp + # stdio.h entrypoints libc.src.stdio.clearerr libc.src.stdio.clearerr_unlocked diff --git a/libc/config/linux/riscv64/headers.txt b/libc/config/linux/riscv64/headers.txt --- a/libc/config/linux/riscv64/headers.txt +++ b/libc/config/linux/riscv64/headers.txt @@ -10,6 +10,7 @@ libc.include.sched libc.include.signal libc.include.spawn + libc.include.setjmp libc.include.stdio libc.include.stdlib libc.include.string diff --git a/libc/include/llvm-libc-types/jmp_buf.h b/libc/include/llvm-libc-types/jmp_buf.h --- a/libc/include/llvm-libc-types/jmp_buf.h +++ b/libc/include/llvm-libc-types/jmp_buf.h @@ -19,6 +19,19 @@ __UINT64_TYPE__ r15; __UINTPTR_TYPE__ rsp; __UINTPTR_TYPE__ rip; +#elif defined(__riscv) + /* Program counter. */ + long int __pc; + /* Callee-saved registers. */ + long int __regs[12]; + /* Stack pointer. */ + long int __sp; + /* Callee-saved floating point registers. */ +#if __riscv_float_abi_double + double __fpregs[12]; +#elif defined(__riscv_float_abi_single) +#error "__jmp_buf not available for your target architecture." +#endif #else #error "__jmp_buf not available for your target architecture." #endif diff --git a/libc/src/setjmp/CMakeLists.txt b/libc/src/setjmp/CMakeLists.txt --- a/libc/src/setjmp/CMakeLists.txt +++ b/libc/src/setjmp/CMakeLists.txt @@ -1,24 +1,17 @@ +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_ARCHITECTURE}) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_ARCHITECTURE}) +endif() + add_entrypoint_object( setjmp - SRCS - setjmp.cpp - HDRS - setjmp_impl.h - COMPILE_OPTIONS - -O3 # We do not want any local variables in setjmp - -fno-omit-frame-pointer # The implementation assumes frame pointer on to the stack + ALIAS DEPENDS - libc.include.setjmp + .${LIBC_TARGET_ARCHITECTURE}.setjmp ) add_entrypoint_object( longjmp - SRCS - longjmp.cpp - HDRS - longjmp.h - COMPILE_OPTIONS - -O3 # We do not want any local variables in longjmp + ALIAS DEPENDS - libc.include.setjmp + .${LIBC_TARGET_ARCHITECTURE}.longjmp ) diff --git a/libc/src/setjmp/CMakeLists.txt b/libc/src/setjmp/riscv64/CMakeLists.txt copy from libc/src/setjmp/CMakeLists.txt copy to libc/src/setjmp/riscv64/CMakeLists.txt --- a/libc/src/setjmp/CMakeLists.txt +++ b/libc/src/setjmp/riscv64/CMakeLists.txt @@ -3,12 +3,12 @@ SRCS setjmp.cpp HDRS - setjmp_impl.h - COMPILE_OPTIONS - -O3 # We do not want any local variables in setjmp - -fno-omit-frame-pointer # The implementation assumes frame pointer on to the stack + ../setjmp_impl.h DEPENDS libc.include.setjmp + COMPILE_OPTIONS + -O3 + -fomit-frame-pointer ) add_entrypoint_object( @@ -16,9 +16,10 @@ SRCS longjmp.cpp HDRS - longjmp.h - COMPILE_OPTIONS - -O3 # We do not want any local variables in longjmp + ../longjmp.h DEPENDS libc.include.setjmp + COMPILE_OPTIONS + -O3 + -fomit-frame-pointer ) diff --git a/libc/src/setjmp/riscv64/longjmp.cpp b/libc/src/setjmp/riscv64/longjmp.cpp new file mode 100644 --- /dev/null +++ b/libc/src/setjmp/riscv64/longjmp.cpp @@ -0,0 +1,58 @@ +//===-- 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" + +#include + +#if !defined(LIBC_TARGET_ARCH_IS_RISCV64) +#error "Invalid file include" +#endif + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(void, longjmp, (__jmp_buf * buf, int val)) { + LIBC_INLINE_ASM("ld ra, %0\n\t" : : "m"(buf->__pc) :); + LIBC_INLINE_ASM("ld s0, %0\n\t" : : "m"(buf->__regs[0]) :); + LIBC_INLINE_ASM("ld s1, %0\n\t" : : "m"(buf->__regs[1]) :); + LIBC_INLINE_ASM("ld s2, %0\n\t" : : "m"(buf->__regs[2]) :); + LIBC_INLINE_ASM("ld s3, %0\n\t" : : "m"(buf->__regs[3]) :); + LIBC_INLINE_ASM("ld s4, %0\n\t" : : "m"(buf->__regs[4]) :); + LIBC_INLINE_ASM("ld s5, %0\n\t" : : "m"(buf->__regs[5]) :); + LIBC_INLINE_ASM("ld s6, %0\n\t" : : "m"(buf->__regs[6]) :); + LIBC_INLINE_ASM("ld s7, %0\n\t" : : "m"(buf->__regs[7]) :); + LIBC_INLINE_ASM("ld s8, %0\n\t" : : "m"(buf->__regs[8]) :); + LIBC_INLINE_ASM("ld s9, %0\n\t" : : "m"(buf->__regs[9]) :); + LIBC_INLINE_ASM("ld s10, %0\n\t" : : "m"(buf->__regs[10]) :); + LIBC_INLINE_ASM("ld s11, %0\n\t" : : "m"(buf->__regs[11]) :); + LIBC_INLINE_ASM("ld sp, %0\n\t" : : "m"(buf->__sp) :); + +#if __riscv_float_abi_double + LIBC_INLINE_ASM("fld fs0, %0\n\t" : : "m"(buf->__fpregs[0]) :); + LIBC_INLINE_ASM("fld fs1, %0\n\t" : : "m"(buf->__fpregs[1]) :); + LIBC_INLINE_ASM("fld fs2, %0\n\t" : : "m"(buf->__fpregs[2]) :); + LIBC_INLINE_ASM("fld fs3, %0\n\t" : : "m"(buf->__fpregs[3]) :); + LIBC_INLINE_ASM("fld fs4, %0\n\t" : : "m"(buf->__fpregs[4]) :); + LIBC_INLINE_ASM("fld fs5, %0\n\t" : : "m"(buf->__fpregs[5]) :); + LIBC_INLINE_ASM("fld fs6, %0\n\t" : : "m"(buf->__fpregs[6]) :); + LIBC_INLINE_ASM("fld fs7, %0\n\t" : : "m"(buf->__fpregs[7]) :); + LIBC_INLINE_ASM("fld fs8, %0\n\t" : : "m"(buf->__fpregs[8]) :); + LIBC_INLINE_ASM("fld fs9, %0\n\t" : : "m"(buf->__fpregs[9]) :); + LIBC_INLINE_ASM("fld fs10, %0\n\t" : : "m"(buf->__fpregs[10]) :); + LIBC_INLINE_ASM("fld fs11, %0\n\t" : : "m"(buf->__fpregs[11]) :); +#elif defined(__riscv_float_abi_single) +#error "longjmp implementation not available for the target architecture." +#endif + + val = val == 0 ? 1 : val; + LIBC_INLINE_ASM("add a0, %0, zero\n\t" : : "r"(val) :); +} + +} // namespace __llvm_libc diff --git a/libc/src/setjmp/riscv64/setjmp.cpp b/libc/src/setjmp/riscv64/setjmp.cpp new file mode 100644 --- /dev/null +++ b/libc/src/setjmp/riscv64/setjmp.cpp @@ -0,0 +1,56 @@ +//===-- 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" + +#include + +#if !defined(LIBC_TARGET_ARCH_IS_RISCV64) +#error "Invalid file include" +#endif + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(int, setjmp, (__jmp_buf * buf)) { + LIBC_INLINE_ASM("sd ra, %0\n\t" : : "m"(buf->__pc) :); + LIBC_INLINE_ASM("sd s0, %0\n\t" : : "m"(buf->__regs[0]) :); + LIBC_INLINE_ASM("sd s1, %0\n\t" : : "m"(buf->__regs[1]) :); + LIBC_INLINE_ASM("sd s2, %0\n\t" : : "m"(buf->__regs[2]) :); + LIBC_INLINE_ASM("sd s3, %0\n\t" : : "m"(buf->__regs[3]) :); + LIBC_INLINE_ASM("sd s4, %0\n\t" : : "m"(buf->__regs[4]) :); + LIBC_INLINE_ASM("sd s5, %0\n\t" : : "m"(buf->__regs[5]) :); + LIBC_INLINE_ASM("sd s6, %0\n\t" : : "m"(buf->__regs[6]) :); + LIBC_INLINE_ASM("sd s7, %0\n\t" : : "m"(buf->__regs[7]) :); + LIBC_INLINE_ASM("sd s8, %0\n\t" : : "m"(buf->__regs[8]) :); + LIBC_INLINE_ASM("sd s9, %0\n\t" : : "m"(buf->__regs[9]) :); + LIBC_INLINE_ASM("sd s10, %0\n\t" : : "m"(buf->__regs[10]) :); + LIBC_INLINE_ASM("sd s11, %0\n\t" : : "m"(buf->__regs[11]) :); + LIBC_INLINE_ASM("sd sp, %0\n\t" : : "m"(buf->__sp) :); + +#if __riscv_float_abi_double + LIBC_INLINE_ASM("fsd fs0, %0\n\t" : : "m"(buf->__fpregs[0]) :); + LIBC_INLINE_ASM("fsd fs1, %0\n\t" : : "m"(buf->__fpregs[1]) :); + LIBC_INLINE_ASM("fsd fs2, %0\n\t" : : "m"(buf->__fpregs[2]) :); + LIBC_INLINE_ASM("fsd fs3, %0\n\t" : : "m"(buf->__fpregs[3]) :); + LIBC_INLINE_ASM("fsd fs4, %0\n\t" : : "m"(buf->__fpregs[4]) :); + LIBC_INLINE_ASM("fsd fs5, %0\n\t" : : "m"(buf->__fpregs[5]) :); + LIBC_INLINE_ASM("fsd fs6, %0\n\t" : : "m"(buf->__fpregs[6]) :); + LIBC_INLINE_ASM("fsd fs7, %0\n\t" : : "m"(buf->__fpregs[7]) :); + LIBC_INLINE_ASM("fsd fs8, %0\n\t" : : "m"(buf->__fpregs[8]) :); + LIBC_INLINE_ASM("fsd fs9, %0\n\t" : : "m"(buf->__fpregs[9]) :); + LIBC_INLINE_ASM("fsd fs10, %0\n\t" : : "m"(buf->__fpregs[10]) :); + LIBC_INLINE_ASM("fsd fs11, %0\n\t" : : "m"(buf->__fpregs[11]) :); +#elif defined(__riscv_float_abi_single) +#error "setjmp implementation not available for the target architecture." +#endif + + return 0; +} + +} // namespace __llvm_libc diff --git a/libc/src/setjmp/CMakeLists.txt b/libc/src/setjmp/x86_64/CMakeLists.txt copy from libc/src/setjmp/CMakeLists.txt copy to libc/src/setjmp/x86_64/CMakeLists.txt --- a/libc/src/setjmp/CMakeLists.txt +++ b/libc/src/setjmp/x86_64/CMakeLists.txt @@ -3,12 +3,12 @@ SRCS setjmp.cpp HDRS - setjmp_impl.h - COMPILE_OPTIONS - -O3 # We do not want any local variables in setjmp - -fno-omit-frame-pointer # The implementation assumes frame pointer on to the stack + ../setjmp_impl.h DEPENDS libc.include.setjmp + COMPILE_OPTIONS + -O3 + -fno-omit-frame-pointer ) add_entrypoint_object( @@ -16,9 +16,10 @@ SRCS longjmp.cpp HDRS - longjmp.h - COMPILE_OPTIONS - -O3 # We do not want any local variables in longjmp + ../longjmp.h DEPENDS libc.include.setjmp + COMPILE_OPTIONS + -O3 + -fno-omit-frame-pointer ) diff --git a/libc/src/setjmp/longjmp.cpp b/libc/src/setjmp/x86_64/longjmp.cpp rename from libc/src/setjmp/longjmp.cpp rename to libc/src/setjmp/x86_64/longjmp.cpp --- a/libc/src/setjmp/longjmp.cpp +++ b/libc/src/setjmp/x86_64/longjmp.cpp @@ -8,14 +8,14 @@ #include "src/setjmp/longjmp.h" #include "src/__support/common.h" -#include "src/__support/macros/properties/architectures.h" -#include +#if !defined(LIBC_TARGET_ARCH_IS_X86_64) +#error "Invalid file include" +#endif namespace __llvm_libc { LLVM_LIBC_FUNCTION(void, longjmp, (__jmp_buf * buf, int val)) { -#ifdef LIBC_TARGET_ARCH_IS_X86_64 register __UINT64_TYPE__ rbx __asm__("rbx"); register __UINT64_TYPE__ rbp __asm__("rbp"); register __UINT64_TYPE__ r12 __asm__("r12"); @@ -38,9 +38,6 @@ LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(r15) : "m"(buf->r15) :); LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(rsp) : "m"(buf->rsp) :); LIBC_INLINE_ASM("jmp *%0\n\t" : : "m"(buf->rip)); -#else // LIBC_TARGET_ARCH_IS_X86_64 -#error "longjmp implementation not available for the target architecture." -#endif } } // namespace __llvm_libc diff --git a/libc/src/setjmp/setjmp.cpp b/libc/src/setjmp/x86_64/setjmp.cpp rename from libc/src/setjmp/setjmp.cpp rename to libc/src/setjmp/x86_64/setjmp.cpp --- a/libc/src/setjmp/setjmp.cpp +++ b/libc/src/setjmp/x86_64/setjmp.cpp @@ -7,15 +7,15 @@ //===----------------------------------------------------------------------===// #include "src/__support/common.h" -#include "src/__support/macros/properties/architectures.h" #include "src/setjmp/setjmp_impl.h" -#include +#if !defined(LIBC_TARGET_ARCH_IS_X86_64) +#error "Invalid file include" +#endif namespace __llvm_libc { LLVM_LIBC_FUNCTION(int, setjmp, (__jmp_buf * buf)) { -#ifdef LIBC_TARGET_ARCH_IS_X86_64 register __UINT64_TYPE__ rbx __asm__("rbx"); register __UINT64_TYPE__ r12 __asm__("r12"); register __UINT64_TYPE__ r13 __asm__("r13"); @@ -50,10 +50,6 @@ buf->rsp = reinterpret_cast<__UINTPTR_TYPE__>(__builtin_frame_address(0)) + sizeof(__UINTPTR_TYPE__) * 2; buf->rip = reinterpret_cast<__UINTPTR_TYPE__>(__builtin_return_address(0)); -#else // LIBC_TARGET_ARCH_IS_X86_64 -#error "setjmp implementation not available for the target architecture." -#endif - return 0; }