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}