diff --git a/include/fast_io_hosted/platforms/linux/aarch64.h b/include/fast_io_hosted/platforms/linux/aarch64.h index f2458f5c..44c3ddaa 100644 --- a/include/fast_io_hosted/platforms/linux/aarch64.h +++ b/include/fast_io_hosted/platforms/linux/aarch64.h @@ -1,5 +1,9 @@ #pragma once +#include +#include +#include + namespace fast_io { @@ -24,6 +28,7 @@ inline return_value_type system_call(auto p1) noexcept } template <::std::uint_least64_t syscall_number> +[[noreturn]] inline void system_call_no_return(auto p1) noexcept { register ::std::uint_least64_t x8 __asm__("x8") = syscall_number; @@ -43,6 +48,18 @@ inline return_value_type system_call(auto p1, auto p2) noexcept return static_cast(x0); } +template <::std::uint_least64_t syscall_number, ::std::signed_integral return_value_type> + requires(1 < sizeof(return_value_type)) +[[__gnu__::__always_inline__]] +inline return_value_type inline_syscall(auto p1, auto p2) noexcept +{ + register ::std::uint_least64_t x8 __asm__("x8") = syscall_number; + register ::std::uint_least64_t x0 __asm__("x0") = (::std::uint_least64_t)p1; + register ::std::uint_least64_t x1 __asm__("x1") = (::std::uint_least64_t)p2; + __asm__ __volatile__("svc 0" : "=r"(x0) : "r"(x8), "0"(x0), "r"(x1) : "memory", "cc"); + return static_cast(x0); +} + template <::std::uint_least64_t syscall_number, ::std::signed_integral return_value_type> requires(1 < sizeof(return_value_type)) inline return_value_type system_call(auto p1, auto p2, auto p3) noexcept @@ -101,6 +118,7 @@ inline return_value_type system_call(auto p1, auto p2, auto p3, auto p4, auto p5 } template <::std::integral I> +[[noreturn]] inline void fast_exit(I ret) noexcept { system_call_no_return<__NR_exit>(ret); diff --git a/include/fast_io_hosted/platforms/linux/amd64.h b/include/fast_io_hosted/platforms/linux/amd64.h index 5994ab9d..b6f097a5 100644 --- a/include/fast_io_hosted/platforms/linux/amd64.h +++ b/include/fast_io_hosted/platforms/linux/amd64.h @@ -1,6 +1,10 @@ #pragma once // https://github.com/bminor/glibc/master/sysdeps/unix/sysv/linux/x86_64/sysdep.h +#include +#include +#include + namespace fast_io { @@ -31,6 +35,7 @@ inline return_value_type system_call(auto p1) noexcept } template <::std::uint_least64_t syscall_number> +[[noreturn]] inline void system_call_no_return(auto p1) noexcept { ::std::uint_least64_t ret; @@ -55,6 +60,20 @@ inline return_value_type system_call(auto p1, auto p2) noexcept return ret; } +template <::std::uint_least64_t syscall_number, ::std::signed_integral return_value_type> + requires(1 < sizeof(return_value_type)) +[[__gnu__::__always_inline__]] +inline return_value_type inline_syscall(auto p1, auto p2) noexcept +{ + return_value_type ret; + __asm__ __volatile__("syscall" + : "=a"(ret) + // EDI RSI RDX + : "0"(syscall_number), "D"(p1), "S"(p2) + : "memory", "cc", "r11", "cx"); + return ret; +} + template <::std::uint_least64_t syscall_number, ::std::signed_integral return_value_type> requires(1 < sizeof(return_value_type)) inline return_value_type system_call(auto p1, auto p2, auto p3) noexcept @@ -114,6 +133,7 @@ inline return_value_type system_call(auto p1, auto p2, auto p3, auto p4, auto p5 } template <::std::integral I> +[[noreturn]] inline void fast_exit(I ret) noexcept { system_call_no_return<__NR_exit>(ret); diff --git a/include/fast_io_hosted/platforms/linux/generic.h b/include/fast_io_hosted/platforms/linux/generic.h index 5cc440f8..794379e7 100644 --- a/include/fast_io_hosted/platforms/linux/generic.h +++ b/include/fast_io_hosted/platforms/linux/generic.h @@ -1,4 +1,8 @@ #pragma once + +#include +#include +#include #include #include @@ -13,7 +17,16 @@ inline return_value_type system_call(Args... args) noexcept return static_cast(ret); } +template <::std::uint_least64_t syscall_number, ::std::signed_integral return_value_type> + requires(1 < sizeof(return_value_type)) +[[__gnu__::__always_inline__]] +inline return_value_type inline_syscall(auto p1, auto p2) noexcept +{ + static_assert(false, "force inline for generic syscall is not supported"); +} + template <::std::size_t syscall_number> +[[noreturn]] inline void system_call_no_return(auto p1) noexcept { ::syscall(syscall_number, p1); @@ -21,6 +34,7 @@ inline void system_call_no_return(auto p1) noexcept } template <::std::integral I> +[[noreturn]] inline void fast_exit(I ret) noexcept { system_call_no_return<__NR_exit>(ret); diff --git a/include/fast_io_hosted/platforms/linux/loongarch64.h b/include/fast_io_hosted/platforms/linux/loongarch64.h index d3dbe486..5a4426b5 100644 --- a/include/fast_io_hosted/platforms/linux/loongarch64.h +++ b/include/fast_io_hosted/platforms/linux/loongarch64.h @@ -5,6 +5,10 @@ glibc loongarch loongarch syscall is very similar to riscv. but it is using syscall instruction like x86_64 */ +#include +#include +#include + namespace fast_io { @@ -31,13 +35,14 @@ inline return_value_type system_call(auto p1) noexcept } template <::std::uint_least64_t syscall_number> +[[noreturn]] inline void system_call_no_return(auto p1) noexcept { register ::std::uint_least64_t a7 __asm__("$a7") = syscall_number; register ::std::uint_least64_t a0 __asm__("$a0") = (::std::uint_least64_t)p1; __asm__ __volatile__("syscall 0" : "+r"(a0) : "r"(a7) : "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "memory"); - __builtin_unreachable(); + __builtin_unreachable(); } template <::std::uint_least64_t syscall_number, ::std::signed_integral return_value_type> @@ -52,6 +57,19 @@ inline return_value_type system_call(auto p1, auto p2) noexcept return static_cast(a0); } +template <::std::uint_least64_t syscall_number, ::std::signed_integral return_value_type> + requires(1 < sizeof(return_value_type)) +[[__gnu__::__always_inline__]] +inline return_value_type inline_syscall(auto p1, auto p2) noexcept +{ + register ::std::uint_least64_t a7 __asm__("$a7") = syscall_number; + register ::std::uint_least64_t a0 __asm__("$a0") = (::std::uint_least64_t)p1; + register ::std::uint_least64_t a1 __asm__("$a1") = (::std::uint_least64_t)p2; + __asm__ __volatile__("syscall 0" : "+r"(a0) : "r"(a7), "r"(a1) : "$t0", "$t1", "$t2", "$t3", "$t4", + "$t5", "$t6", "$t7", "$t8", "memory"); + return static_cast(a0); +} + template <::std::uint_least64_t syscall_number, ::std::signed_integral return_value_type> requires(1 < sizeof(return_value_type)) inline return_value_type system_call(auto p1, auto p2, auto p3) noexcept @@ -111,6 +129,7 @@ inline return_value_type system_call(auto p1, auto p2, auto p3, auto p4, auto p5 } template <::std::integral I> +[[noreturn]] inline void fast_exit(I ret) noexcept { system_call_no_return<__NR_exit>(ret); diff --git a/include/fast_io_hosted/platforms/linux/riscv64.h b/include/fast_io_hosted/platforms/linux/riscv64.h index bdc1786d..5d547e45 100644 --- a/include/fast_io_hosted/platforms/linux/riscv64.h +++ b/include/fast_io_hosted/platforms/linux/riscv64.h @@ -5,6 +5,10 @@ Do we need to deal with big endian with extra code??? */ +#include +#include +#include + namespace fast_io { @@ -29,6 +33,7 @@ inline return_value_type system_call(auto p1) noexcept } template <::std::uint_least64_t syscall_number> +[[noreturn]] inline void system_call_no_return(auto p1) noexcept { register ::std::uint_least64_t a7 __asm__("a7") = syscall_number; @@ -48,6 +53,18 @@ inline return_value_type system_call(auto p1, auto p2) noexcept return static_cast(a0); } +template <::std::uint_least64_t syscall_number, ::std::signed_integral return_value_type> + requires(1 < sizeof(return_value_type)) +[[__gnu__::__always_inline__]] +inline return_value_type inline_syscall(auto p1, auto p2) noexcept +{ + register ::std::uint_least64_t a7 __asm__("a7") = syscall_number; + register ::std::uint_least64_t a0 __asm__("a0") = (::std::uint_least64_t)p1; + register ::std::uint_least64_t a1 __asm__("a1") = (::std::uint_least64_t)p2; + __asm__ __volatile__("ecall" : "+r"(a0) : "r"(a7), "r"(a1) : "memory"); + return static_cast(a0); +} + template <::std::uint_least64_t syscall_number, ::std::signed_integral return_value_type> requires(1 < sizeof(return_value_type)) inline return_value_type system_call(auto p1, auto p2, auto p3) noexcept @@ -103,6 +120,7 @@ inline return_value_type system_call(auto p1, auto p2, auto p3, auto p4, auto p5 } template <::std::integral I> +[[noreturn]] inline void fast_exit(I ret) noexcept { system_call_no_return<__NR_exit>(ret);