2017-09-16 06:18:54 +08:00
|
|
|
#![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
|
|
|
|
|
2017-09-16 07:04:11 +08:00
|
|
|
#[cfg(all(windows, target_env = "gnu", not(feature = "mangled-names")))]
|
2017-09-16 06:18:54 +08:00
|
|
|
#[naked]
|
2017-09-16 07:04:11 +08:00
|
|
|
#[no_mangle]
|
2017-09-16 06:18:54 +08:00
|
|
|
pub unsafe fn ___chkstk_ms() {
|
|
|
|
asm!("
|
|
|
|
push %ecx
|
|
|
|
push %eax
|
|
|
|
cmp $$0x1000,%eax
|
|
|
|
lea 12(%esp),%ecx
|
|
|
|
jb 1f
|
|
|
|
2:
|
|
|
|
sub $$0x1000,%ecx
|
|
|
|
test %ecx,(%ecx)
|
|
|
|
sub $$0x1000,%eax
|
|
|
|
cmp $$0x1000,%eax
|
|
|
|
ja 2b
|
|
|
|
1:
|
|
|
|
sub %eax,%ecx
|
|
|
|
test %ecx,(%ecx)
|
|
|
|
pop %eax
|
|
|
|
pop %ecx
|
|
|
|
ret");
|
|
|
|
intrinsics::unreachable();
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: __alloca should be an alias to __chkstk
|
2017-09-16 07:04:11 +08:00
|
|
|
#[cfg(all(windows, target_env = "gnu", not(feature = "mangled-names")))]
|
2017-09-16 06:18:54 +08:00
|
|
|
#[naked]
|
2017-09-16 07:04:11 +08:00
|
|
|
#[no_mangle]
|
2017-09-16 06:18:54 +08:00
|
|
|
pub unsafe fn __alloca() {
|
|
|
|
asm!("jmp ___chkstk // Jump to ___chkstk since fallthrough may be unreliable");
|
|
|
|
intrinsics::unreachable();
|
|
|
|
}
|
|
|
|
|
2017-09-16 07:04:11 +08:00
|
|
|
#[cfg(all(windows, target_env = "gnu", not(feature = "mangled-names")))]
|
2017-09-16 06:18:54 +08:00
|
|
|
#[naked]
|
2017-09-16 07:04:11 +08:00
|
|
|
#[no_mangle]
|
2017-09-16 06:18:54 +08:00
|
|
|
pub unsafe fn ___chkstk() {
|
|
|
|
asm!("
|
|
|
|
push %ecx
|
|
|
|
cmp $$0x1000,%eax
|
|
|
|
lea 8(%esp),%ecx // esp before calling this routine -> ecx
|
|
|
|
jb 1f
|
|
|
|
2:
|
|
|
|
sub $$0x1000,%ecx
|
|
|
|
test %ecx,(%ecx)
|
|
|
|
sub $$0x1000,%eax
|
|
|
|
cmp $$0x1000,%eax
|
|
|
|
ja 2b
|
|
|
|
1:
|
|
|
|
sub %eax,%ecx
|
|
|
|
test %ecx,(%ecx)
|
|
|
|
|
|
|
|
lea 4(%esp),%eax // load pointer to the return address into eax
|
|
|
|
mov %ecx,%esp // install the new top of stack pointer into esp
|
|
|
|
mov -4(%eax),%ecx // restore ecx
|
|
|
|
push (%eax) // push return address onto the stack
|
|
|
|
sub %esp,%eax // restore the original value in eax
|
|
|
|
ret");
|
|
|
|
intrinsics::unreachable();
|
|
|
|
}
|