#![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 intrinsics! { #[naked] #[cfg(all( windows, target_env = "gnu", not(feature = "no-asm") ))] pub unsafe extern "C" fn ___chkstk_ms() { core::arch::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", options(noreturn, att_syntax) ); } // FIXME: __alloca should be an alias to __chkstk #[naked] #[cfg(all( windows, target_env = "gnu", not(feature = "no-asm") ))] pub unsafe extern "C" fn __alloca() { core::arch::asm!( "jmp ___chkstk", // Jump to ___chkstk since fallthrough may be unreliable" options(noreturn, att_syntax) ); } #[naked] #[cfg(all( windows, target_env = "gnu", not(feature = "no-asm") ))] pub unsafe extern "C" fn ___chkstk() { core::arch::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", options(noreturn, att_syntax) ); } }