compiler_builtins/x86.rs
1#![allow(unused_imports)]
2
3use core::intrinsics;
4
5// NOTE These functions are implemented using assembly because they using a custom
6// calling convention which can't be implemented using a normal Rust function
7
8// NOTE These functions are never mangled as they are not tested against compiler-rt
9
10intrinsics! {
11 #[unsafe(naked)]
12 #[cfg(all(
13 any(all(windows, target_env = "gnu"), target_os = "uefi"),
14 not(feature = "no-asm")
15 ))]
16 pub unsafe extern "C" fn __chkstk() {
17 core::arch::naked_asm!(
18 "jmp __alloca", // Jump to __alloca since fallthrough may be unreliable"
19 options(att_syntax)
20 );
21 }
22
23 #[unsafe(naked)]
24 #[cfg(all(
25 any(all(windows, target_env = "gnu"), target_os = "uefi"),
26 not(feature = "no-asm")
27 ))]
28 pub unsafe extern "C" fn _alloca() {
29 // __chkstk and _alloca are the same function
30 core::arch::naked_asm!(
31 "push %ecx",
32 "cmp $0x1000,%eax",
33 "lea 8(%esp),%ecx", // esp before calling this routine -> ecx
34 "jb 1f",
35 "2:",
36 "sub $0x1000,%ecx",
37 "test %ecx,(%ecx)",
38 "sub $0x1000,%eax",
39 "cmp $0x1000,%eax",
40 "ja 2b",
41 "1:",
42 "sub %eax,%ecx",
43 "test %ecx,(%ecx)",
44 "lea 4(%esp),%eax", // load pointer to the return address into eax
45 "mov %ecx,%esp", // install the new top of stack pointer into esp
46 "mov -4(%eax),%ecx", // restore ecx
47 "push (%eax)", // push return address onto the stack
48 "sub %esp,%eax", // restore the original value in eax
49 "ret",
50 options(att_syntax)
51 );
52 }
53}