diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index 9df5f6ad..d9098584 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -13,6 +13,7 @@ set(SOURCES src/ctype.cpp src/time.cpp src/init.cpp + src/setjmp.cpp src/sys/stat.cpp src/sys/mman.cpp src/sys/wait.cpp @@ -22,6 +23,7 @@ if(${LUNA_ARCH} STREQUAL "x86_64") set(SOURCES ${SOURCES} src/arch/x86_64/syscall.S + src/arch/x86_64/setjmp.S ) endif() diff --git a/libc/include/bits/attrs.h b/libc/include/bits/attrs.h index 90de54d0..c9fa83bd 100644 --- a/libc/include/bits/attrs.h +++ b/libc/include/bits/attrs.h @@ -3,7 +3,7 @@ #ifndef _BITS_ATTRS_H #define _BITS_ATTRS_H -#if !defined(_STDLIB_H) && !defined(_STRING_H) && !defined(_ASSERT_H) +#if !defined(_STDLIB_H) && !defined(_STRING_H) && !defined(_ASSERT_H) && !defined(_SETJMP_H) #error "Never include bits/attrs.h directly; use one of the standard library headers." #endif diff --git a/libc/include/bits/fixed-size-types.h b/libc/include/bits/fixed-size-types.h index 2003b0e9..0b700841 100644 --- a/libc/include/bits/fixed-size-types.h +++ b/libc/include/bits/fixed-size-types.h @@ -3,7 +3,7 @@ #ifndef _BITS_FIXED_SIZE_TYPES_H #define _BITS_FIXED_SIZE_TYPES_H -#ifndef _SYS_TYPES_H +#if !defined(_SYS_TYPES_H) && !defined(_BITS_SETJMP_TYPES_H) #error "Never include bits/fixed-size-types.h, use the standard header instead." #endif diff --git a/libc/include/bits/platform.h b/libc/include/bits/platform.h new file mode 100644 index 00000000..31930401 --- /dev/null +++ b/libc/include/bits/platform.h @@ -0,0 +1,13 @@ +/* bits/platform.h: Platform defines. */ + +#ifndef _BITS_PLATFORM_H +#define _BITS_PLATFORM_H + +#if defined(__x86_64__) +#define __libc_arch_x86_64 +#define __libc_arch_x86 +#else +#define __libc_arch_unknown +#endif + +#endif diff --git a/libc/include/bits/setjmp-types.h b/libc/include/bits/setjmp-types.h new file mode 100644 index 00000000..439f7a38 --- /dev/null +++ b/libc/include/bits/setjmp-types.h @@ -0,0 +1,20 @@ +/* bits/setjmp-types.h: Architecture-dependent definitions for jmp_buf/sigjmp_buf. */ + +#ifndef _BITS_SETJMP_TYPES_H +#define _BITS_SETJMP_TYPES_H + +#include +#include + +#ifndef _SETJMP_H +#error "Never use bits/setjmp-types.h directly; include setjmp.h instead." +#endif + +#ifdef __libc_arch_x86_64 +typedef __u64_t jmp_buf[8]; +typedef __u64_t sigjmp_buf[8]; +#else +#error "Unsupported architecture." +#endif + +#endif diff --git a/libc/include/setjmp.h b/libc/include/setjmp.h new file mode 100644 index 00000000..9538c94f --- /dev/null +++ b/libc/include/setjmp.h @@ -0,0 +1,30 @@ +/* setjmp.h: nonlocal gotos. */ + +#ifndef _SETJMP_H +#define _SETJMP_H + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* Saves the current execution state in env. */ + int setjmp(jmp_buf env); + + /* Right now, does the exact same thing as setjmp() (savesigs is ignored), since signals are not implemented. */ + int sigsetjmp(sigjmp_buf env, int savesigs); + + /* Restores the execution state saved in env by a setjmp() call. */ + __noreturn void longjmp(jmp_buf env, int val); + + /* Right now, does the exact same as longjmp(), since signals are not implemented. */ + __noreturn void siglongjmp(sigjmp_buf env, int val); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libc/src/arch/x86_64/setjmp.S b/libc/src/arch/x86_64/setjmp.S new file mode 100644 index 00000000..ab37bfe5 --- /dev/null +++ b/libc/src/arch/x86_64/setjmp.S @@ -0,0 +1,36 @@ +.global _setjmp +.global setjmp +_setjmp: +setjmp: + mov $0, %rsi + mov %rbx, (%rdi) + mov %r12, 0x8(%rdi) + mov %r13, 0x10(%rdi) + mov %r14, 0x18(%rdi) + mov %r15, 0x20(%rdi) + mov %rbp, 0x28(%rdi) + mov %rsp, 0x30(%rdi) + mov (%rsp), %rax + mov %rax, 0x38(%rdi) + xor %rax, %rax + ret + +.global _longjmp +.global longjmp +_longjmp: +longjmp: + mov %rsi, %rax + cmp $0, %rax + jne .nonzero + mov $1, %rax +.nonzero: + mov (%rdi), %rbx + mov 0x8(%rdi), %r12 + mov 0x10(%rdi), %r13 + mov 0x18(%rdi), %r14 + mov 0x20(%rdi), %r15 + mov 0x28(%rdi), %rbp + mov 0x30(%rdi), %rsp + mov 0x38(%rdi), %rcx + mov %rcx, (%rsp) + ret diff --git a/libc/src/setjmp.cpp b/libc/src/setjmp.cpp new file mode 100644 index 00000000..2d2bf673 --- /dev/null +++ b/libc/src/setjmp.cpp @@ -0,0 +1,14 @@ +#include + +extern "C" +{ + int sigsetjmp(sigjmp_buf env, int) + { + return setjmp(env); + } + + __noreturn void siglongjmp(sigjmp_buf env, int val) + { + longjmp(env, val); + } +}