//
// Note that x86 Windows uses the "thiscall" calling convention for C++ member
// functions instead of the default "C" calling convention.
-cfg_if::cfg_if! {
- if #[cfg(target_arch = "x86")] {
- unsafe extern "thiscall" fn exception_cleanup(e: *mut [u64; 2]) {
- if (*e)[0] != 0 {
- cleanup(*e);
- }
- }
- unsafe extern "thiscall" fn exception_copy(_dest: *mut [u64; 2],
- _src: *mut [u64; 2])
- -> *mut [u64; 2] {
- panic!("Rust panics cannot be copied");
- }
- } else {
- unsafe extern "C" fn exception_cleanup(e: *mut [u64; 2]) {
+//
+// The exception_copy function is a bit special here: it is invoked by the MSVC
+// runtime under a try/catch block and the panic that we generate here will be
+// used as the result of the exception copy. This is used by the C++ runtime to
+// support capturing exceptions with std::exception_ptr, which we can't support
+// because Box<dyn Any> isn't clonable.
+macro_rules! define_cleanup {
+ ($abi:tt) => {
+ unsafe extern $abi fn exception_cleanup(e: *mut [u64; 2]) {
if (*e)[0] != 0 {
cleanup(*e);
+ super::__rust_drop_panic();
}
}
- unsafe extern "C" fn exception_copy(_dest: *mut [u64; 2],
- _src: *mut [u64; 2])
- -> *mut [u64; 2] {
+ #[unwind(allowed)]
+ unsafe extern $abi fn exception_copy(_dest: *mut [u64; 2],
+ _src: *mut [u64; 2])
+ -> *mut [u64; 2] {
panic!("Rust panics cannot be copied");
}
}
}
+cfg_if::cfg_if! {
+ if #[cfg(target_arch = "x86")] {
+ define_cleanup!("thiscall");
+ } else {
+ define_cleanup!("C");
+ }
+}
pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
use core::intrinsics::atomic_store;