a6ecd1a73f
Use the "volatile" option and the "memory" clobber on inline asm that does things like return directly, to reduce the chances of compilers rearranging the code.
76 lines
2.2 KiB
Rust
76 lines
2.2 KiB
Rust
#![allow(unused_imports)]
|
|
|
|
use core::intrinsics;
|
|
|
|
// NOTE These functions are implemented using assembly because they using a custom
|
|
// calling convention which can't be implemented using a normal Rust function
|
|
|
|
// NOTE These functions are never mangled as they are not tested against compiler-rt
|
|
// and mangling ___chkstk would break the `jmp ___chkstk` instruction in __alloca
|
|
|
|
#[cfg(all(windows, target_env = "gnu", not(feature = "mangled-names")))]
|
|
#[naked]
|
|
#[no_mangle]
|
|
pub unsafe fn ___chkstk_ms() {
|
|
asm!("
|
|
push %rcx
|
|
push %rax
|
|
cmp $$0x1000,%rax
|
|
lea 24(%rsp),%rcx
|
|
jb 1f
|
|
2:
|
|
sub $$0x1000,%rcx
|
|
test %rcx,(%rcx)
|
|
sub $$0x1000,%rax
|
|
cmp $$0x1000,%rax
|
|
ja 2b
|
|
1:
|
|
sub %rax,%rcx
|
|
test %rcx,(%rcx)
|
|
pop %rax
|
|
pop %rcx
|
|
ret" ::: "memory" : "volatile");
|
|
intrinsics::unreachable();
|
|
}
|
|
|
|
#[cfg(all(windows, target_env = "gnu", not(feature = "mangled-names")))]
|
|
#[naked]
|
|
#[no_mangle]
|
|
pub unsafe fn __alloca() {
|
|
asm!("mov %rcx,%rax // x64 _alloca is a normal function with parameter in rcx
|
|
jmp ___chkstk // Jump to ___chkstk since fallthrough may be unreliable"
|
|
::: "memory" : "volatile");
|
|
intrinsics::unreachable();
|
|
}
|
|
|
|
#[cfg(all(windows, target_env = "gnu", not(feature = "mangled-names")))]
|
|
#[naked]
|
|
#[no_mangle]
|
|
pub unsafe fn ___chkstk() {
|
|
asm!(
|
|
"
|
|
push %rcx
|
|
cmp $$0x1000,%rax
|
|
lea 16(%rsp),%rcx // rsp before calling this routine -> rcx
|
|
jb 1f
|
|
2:
|
|
sub $$0x1000,%rcx
|
|
test %rcx,(%rcx)
|
|
sub $$0x1000,%rax
|
|
cmp $$0x1000,%rax
|
|
ja 2b
|
|
1:
|
|
sub %rax,%rcx
|
|
test %rcx,(%rcx)
|
|
|
|
lea 8(%rsp),%rax // load pointer to the return address into rax
|
|
mov %rcx,%rsp // install the new top of stack pointer into rsp
|
|
mov -8(%rax),%rcx // restore rcx
|
|
push (%rax) // push return address onto the stack
|
|
sub %rsp,%rax // restore the original value in rax
|
|
ret"
|
|
::: "memory" : "volatile"
|
|
);
|
|
intrinsics::unreachable();
|
|
}
|