summaryrefslogtreecommitdiffstats
path: root/vendor/compiler_builtins/src/x86.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/compiler_builtins/src/x86.rs')
-rw-r--r--vendor/compiler_builtins/src/x86.rs85
1 files changed, 85 insertions, 0 deletions
diff --git a/vendor/compiler_builtins/src/x86.rs b/vendor/compiler_builtins/src/x86.rs
new file mode 100644
index 000000000..fd1f32e3a
--- /dev/null
+++ b/vendor/compiler_builtins/src/x86.rs
@@ -0,0 +1,85 @@
+#![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)
+ );
+ }
+}