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// and mangling ___chkstk would break the `jmp ___chkstk` instruction in __alloca
10
11intrinsics! {
12 #[naked]
13 #[cfg(all(
14 any(all(windows, target_env = "gnu"), target_os = "uefi"),
15 not(feature = "no-asm")
16 ))]
17 pub unsafe extern "C" fn ___chkstk_ms() {
18 core::arch::asm!(
19 "push %rcx",
20 "push %rax",
21 "cmp $0x1000,%rax",
22 "lea 24(%rsp),%rcx",
23 "jb 1f",
24 "2:",
25 "sub $0x1000,%rcx",
26 "test %rcx,(%rcx)",
27 "sub $0x1000,%rax",
28 "cmp $0x1000,%rax",
29 "ja 2b",
30 "1:",
31 "sub %rax,%rcx",
32 "test %rcx,(%rcx)",
33 "pop %rax",
34 "pop %rcx",
35 "ret",
36 options(noreturn, att_syntax)
37 );
38 }
39
40 #[naked]
41 #[cfg(all(
42 any(all(windows, target_env = "gnu"), target_os = "uefi"),
43 not(feature = "no-asm")
44 ))]
45 pub unsafe extern "C" fn __alloca() {
46 core::arch::asm!(
47 "mov %rcx,%rax", // x64 _alloca is a normal function with parameter in rcx
48 "jmp ___chkstk", // Jump to ___chkstk since fallthrough may be unreliable"
49 options(noreturn, att_syntax)
50 );
51 }
52
53 #[naked]
54 #[cfg(all(
55 any(all(windows, target_env = "gnu"), target_os = "uefi"),
56 not(feature = "no-asm")
57 ))]
58 pub unsafe extern "C" fn ___chkstk() {
59 core::arch::asm!(
60 "push %rcx",
61 "cmp $0x1000,%rax",
62 "lea 16(%rsp),%rcx", // rsp before calling this routine -> rcx
63 "jb 1f",
64 "2:",
65 "sub $0x1000,%rcx",
66 "test %rcx,(%rcx)",
67 "sub $0x1000,%rax",
68 "cmp $0x1000,%rax",
69 "ja 2b",
70 "1:",
71 "sub %rax,%rcx",
72 "test %rcx,(%rcx)",
73 "lea 8(%rsp),%rax", // load pointer to the return address into rax
74 "mov %rcx,%rsp", // install the new top of stack pointer into rsp
75 "mov -8(%rax),%rcx", // restore rcx
76 "push (%rax)", // push return address onto the stack
77 "sub %rsp,%rax", // restore the original value in rax
78 "ret",
79 options(noreturn, att_syntax)
80 );
81 }
82}
83
84// HACK(https://github.com/rust-lang/rust/issues/62785): x86_64-unknown-uefi needs special LLVM
85// support unless we emit the _fltused
86mod _fltused {
87 #[no_mangle]
88 #[used]
89 #[cfg(target_os = "uefi")]
90 static _fltused: i32 = 0;
91}
92