// #include <stdint.h>
//
// struct rust_panic {
+// rust_panic(const rust_panic&);
+// ~rust_panic();
+//
// uint64_t x[2];
-// }
+// };
//
// void foo() {
// rust_panic a = {0, 1};
#[repr(C)]
pub struct _ThrowInfo {
pub attributes: c_uint,
- pub pnfnUnwind: imp::ptr_t,
+ pub pmfnUnwind: imp::ptr_t,
pub pForwardCompat: imp::ptr_t,
pub pCatchableTypeArray: imp::ptr_t,
}
pub pType: imp::ptr_t,
pub thisDisplacement: _PMD,
pub sizeOrOffset: c_int,
- pub copy_function: imp::ptr_t,
+ pub copyFunction: imp::ptr_t,
}
#[repr(C)]
static mut THROW_INFO: _ThrowInfo = _ThrowInfo {
attributes: 0,
- pnfnUnwind: ptr!(0),
+ pmfnUnwind: ptr!(0),
pForwardCompat: ptr!(0),
pCatchableTypeArray: ptr!(0),
};
pType: ptr!(0),
thisDisplacement: _PMD { mdisp: 0, pdisp: -1, vdisp: 0 },
sizeOrOffset: mem::size_of::<[u64; 2]>() as c_int,
- copy_function: ptr!(0),
+ copyFunction: ptr!(0),
};
extern "C" {
name: TYPE_NAME,
};
+// Destructor used if the C++ code decides to capture the exception and drop it
+// without propagating it. The catch part of the try intrinsic will set the
+// first word of the exception object to 0 so that it is skipped by the
+// destructor.
+//
+// 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]) {
+ if (*e)[0] != 0 {
+ cleanup(*e);
+ }
+ }
+ unsafe extern "C" fn exception_copy(_dest: *mut [u64; 2],
+ _src: *mut [u64; 2])
+ -> *mut [u64; 2] {
+ panic!("Rust panics cannot be copied");
+ }
+ }
+}
+
pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
use core::intrinsics::atomic_store;
// exception (constructed above).
let ptrs = mem::transmute::<_, raw::TraitObject>(data);
let mut ptrs = [ptrs.data as u64, ptrs.vtable as u64];
- let ptrs_ptr = ptrs.as_mut_ptr();
- let throw_ptr = ptrs_ptr as *mut _;
+ let throw_ptr = ptrs.as_mut_ptr() as *mut _;
// This... may seems surprising, and justifiably so. On 32-bit MSVC the
// pointers between these structure are just that, pointers. On 64-bit MSVC,
//
// In any case, we basically need to do something like this until we can
// express more operations in statics (and we may never be able to).
+ if !cfg!(bootstrap) {
+ atomic_store(
+ &mut THROW_INFO.pmfnUnwind as *mut _ as *mut u32,
+ ptr!(exception_cleanup) as u32,
+ );
+ }
atomic_store(
&mut THROW_INFO.pCatchableTypeArray as *mut _ as *mut u32,
ptr!(&CATCHABLE_TYPE_ARRAY as *const _) as u32,
&mut CATCHABLE_TYPE.pType as *mut _ as *mut u32,
ptr!(&TYPE_DESCRIPTOR as *const _) as u32,
);
+ if !cfg!(bootstrap) {
+ atomic_store(
+ &mut CATCHABLE_TYPE.copyFunction as *mut _ as *mut u32,
+ ptr!(exception_copy) as u32,
+ );
+ }
extern "system" {
#[unwind(allowed)]