@@ -77,8 +77,11 @@ use libc::{c_int, c_uint, c_void};
7777// #include <stdint.h>
7878//
7979// struct rust_panic {
80+ // rust_panic(const rust_panic&);
81+ // ~rust_panic();
82+ //
8083// uint64_t x[2];
81- // }
84+ // };
8285//
8386// void foo() {
8487// rust_panic a = {0, 1};
@@ -128,7 +131,7 @@ mod imp {
128131#[ repr( C ) ]
129132pub struct _ThrowInfo {
130133 pub attributes : c_uint ,
131- pub pnfnUnwind : imp:: ptr_t ,
134+ pub pmfnUnwind : imp:: ptr_t ,
132135 pub pForwardCompat : imp:: ptr_t ,
133136 pub pCatchableTypeArray : imp:: ptr_t ,
134137}
@@ -145,7 +148,7 @@ pub struct _CatchableType {
145148 pub pType : imp:: ptr_t ,
146149 pub thisDisplacement : _PMD ,
147150 pub sizeOrOffset : c_int ,
148- pub copy_function : imp:: ptr_t ,
151+ pub copyFunction : imp:: ptr_t ,
149152}
150153
151154#[ repr( C ) ]
@@ -168,7 +171,7 @@ const TYPE_NAME: [u8; 11] = *b"rust_panic\0";
168171
169172static mut THROW_INFO : _ThrowInfo = _ThrowInfo {
170173 attributes : 0 ,
171- pnfnUnwind : ptr ! ( 0 ) ,
174+ pmfnUnwind : ptr ! ( 0 ) ,
172175 pForwardCompat : ptr ! ( 0 ) ,
173176 pCatchableTypeArray : ptr ! ( 0 ) ,
174177} ;
@@ -181,7 +184,7 @@ static mut CATCHABLE_TYPE: _CatchableType = _CatchableType {
181184 pType : ptr ! ( 0 ) ,
182185 thisDisplacement : _PMD { mdisp : 0 , pdisp : -1 , vdisp : 0 } ,
183186 sizeOrOffset : mem:: size_of :: < [ u64 ; 2 ] > ( ) as c_int ,
184- copy_function : ptr ! ( 0 ) ,
187+ copyFunction : ptr ! ( 0 ) ,
185188} ;
186189
187190extern "C" {
@@ -208,6 +211,42 @@ static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor {
208211 name : TYPE_NAME ,
209212} ;
210213
214+ // Destructor used if the C++ code decides to capture the exception and drop it
215+ // without propagating it. The catch part of the try intrinsic will set the
216+ // first word of the exception object to 0 so that it is skipped by the
217+ // destructor.
218+ //
219+ // Note that x86 Windows uses the "thiscall" calling convention for C++ member
220+ // functions instead of the default "C" calling convention.
221+ //
222+ // The exception_copy function is a bit special here: it is invoked by the MSVC
223+ // runtime under a try/catch block and the panic that we generate here will be
224+ // used as the result of the exception copy. This is used by the C++ runtime to
225+ // support capturing exceptions with std::exception_ptr, which we can't support
226+ // because Box<dyn Any> isn't clonable.
227+ macro_rules! define_cleanup {
228+ ( $abi: tt) => {
229+ unsafe extern $abi fn exception_cleanup( e: * mut [ u64 ; 2 ] ) {
230+ if ( * e) [ 0 ] != 0 {
231+ cleanup( * e) ;
232+ }
233+ }
234+ #[ unwind( allowed) ]
235+ unsafe extern $abi fn exception_copy( _dest: * mut [ u64 ; 2 ] ,
236+ _src: * mut [ u64 ; 2 ] )
237+ -> * mut [ u64 ; 2 ] {
238+ panic!( "Rust panics cannot be copied" ) ;
239+ }
240+ }
241+ }
242+ cfg_if:: cfg_if! {
243+ if #[ cfg( target_arch = "x86" ) ] {
244+ define_cleanup!( "thiscall" ) ;
245+ } else {
246+ define_cleanup!( "C" ) ;
247+ }
248+ }
249+
211250pub unsafe fn panic ( data : Box < dyn Any + Send > ) -> u32 {
212251 use core:: intrinsics:: atomic_store;
213252
@@ -220,8 +259,7 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
220259 // exception (constructed above).
221260 let ptrs = mem:: transmute :: < _ , raw:: TraitObject > ( data) ;
222261 let mut ptrs = [ ptrs. data as u64 , ptrs. vtable as u64 ] ;
223- let ptrs_ptr = ptrs. as_mut_ptr ( ) ;
224- let throw_ptr = ptrs_ptr as * mut _ ;
262+ let throw_ptr = ptrs. as_mut_ptr ( ) as * mut _ ;
225263
226264 // This... may seems surprising, and justifiably so. On 32-bit MSVC the
227265 // pointers between these structure are just that, pointers. On 64-bit MSVC,
@@ -243,6 +281,12 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
243281 //
244282 // In any case, we basically need to do something like this until we can
245283 // express more operations in statics (and we may never be able to).
284+ if !cfg ! ( bootstrap) {
285+ atomic_store (
286+ & mut THROW_INFO . pmfnUnwind as * mut _ as * mut u32 ,
287+ ptr ! ( exception_cleanup) as u32 ,
288+ ) ;
289+ }
246290 atomic_store (
247291 & mut THROW_INFO . pCatchableTypeArray as * mut _ as * mut u32 ,
248292 ptr ! ( & CATCHABLE_TYPE_ARRAY as * const _) as u32 ,
@@ -255,6 +299,12 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
255299 & mut CATCHABLE_TYPE . pType as * mut _ as * mut u32 ,
256300 ptr ! ( & TYPE_DESCRIPTOR as * const _) as u32 ,
257301 ) ;
302+ if !cfg ! ( bootstrap) {
303+ atomic_store (
304+ & mut CATCHABLE_TYPE . copyFunction as * mut _ as * mut u32 ,
305+ ptr ! ( exception_copy) as u32 ,
306+ ) ;
307+ }
258308
259309 extern "system" {
260310 #[ unwind( allowed) ]
0 commit comments