x86_64.rs 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. #![allow(unused_imports)]
  2. use core::intrinsics;
  3. // NOTE These functions are implemented using assembly because they using a custom
  4. // calling convention which can't be implemented using a normal Rust function
  5. // NOTE These functions are never mangled as they are not tested against compiler-rt
  6. // and mangling ___chkstk would break the `jmp ___chkstk` instruction in __alloca
  7. #[cfg(all(
  8. windows,
  9. target_env = "gnu",
  10. not(feature = "no-asm"),
  11. not(feature = "mangled-names")
  12. ))]
  13. #[naked]
  14. #[no_mangle]
  15. pub unsafe extern "C" fn ___chkstk_ms() {
  16. core::arch::asm!(
  17. "push %rcx",
  18. "push %rax",
  19. "cmp $0x1000,%rax",
  20. "lea 24(%rsp),%rcx",
  21. "jb 1f",
  22. "2:",
  23. "sub $0x1000,%rcx",
  24. "test %rcx,(%rcx)",
  25. "sub $0x1000,%rax",
  26. "cmp $0x1000,%rax",
  27. "ja 2b",
  28. "1:",
  29. "sub %rax,%rcx",
  30. "test %rcx,(%rcx)",
  31. "pop %rax",
  32. "pop %rcx",
  33. "ret",
  34. options(noreturn, att_syntax)
  35. );
  36. }
  37. #[cfg(all(
  38. windows,
  39. target_env = "gnu",
  40. not(feature = "no-asm"),
  41. not(feature = "mangled-names")
  42. ))]
  43. #[naked]
  44. #[no_mangle]
  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. #[cfg(all(
  53. windows,
  54. target_env = "gnu",
  55. not(feature = "no-asm"),
  56. not(feature = "mangled-names")
  57. ))]
  58. #[naked]
  59. #[no_mangle]
  60. pub unsafe extern "C" fn ___chkstk() {
  61. core::arch::asm!(
  62. "push %rcx",
  63. "cmp $0x1000,%rax",
  64. "lea 16(%rsp),%rcx", // rsp before calling this routine -> rcx
  65. "jb 1f",
  66. "2:",
  67. "sub $0x1000,%rcx",
  68. "test %rcx,(%rcx)",
  69. "sub $0x1000,%rax",
  70. "cmp $0x1000,%rax",
  71. "ja 2b",
  72. "1:",
  73. "sub %rax,%rcx",
  74. "test %rcx,(%rcx)",
  75. "lea 8(%rsp),%rax", // load pointer to the return address into rax
  76. "mov %rcx,%rsp", // install the new top of stack pointer into rsp
  77. "mov -8(%rax),%rcx", // restore rcx
  78. "push (%rax)", // push return address onto the stack
  79. "sub %rsp,%rax", // restore the original value in rax
  80. "ret",
  81. options(noreturn, att_syntax)
  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
  86. #[no_mangle]
  87. #[used]
  88. #[cfg(target_os = "uefi")]
  89. static _fltused: i32 = 0;