@@ -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,43 @@ 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+ super :: __rust_drop_panic( ) ;
233+ }
234+ }
235+ #[ unwind( allowed) ]
236+ unsafe extern $abi fn exception_copy( _dest: * mut [ u64 ; 2 ] ,
237+ _src: * mut [ u64 ; 2 ] )
238+ -> * mut [ u64 ; 2 ] {
239+ panic!( "Rust panics cannot be copied" ) ;
240+ }
241+ }
242+ }
243+ cfg_if:: cfg_if! {
244+ if #[ cfg( target_arch = "x86" ) ] {
245+ define_cleanup!( "thiscall" ) ;
246+ } else {
247+ define_cleanup!( "C" ) ;
248+ }
249+ }
250+
211251pub unsafe fn panic ( data : Box < dyn Any + Send > ) -> u32 {
212252 use core:: intrinsics:: atomic_store;
213253
@@ -220,8 +260,7 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
220260 // exception (constructed above).
221261 let ptrs = mem:: transmute :: < _ , raw:: TraitObject > ( data) ;
222262 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 _ ;
263+ let throw_ptr = ptrs. as_mut_ptr ( ) as * mut _ ;
225264
226265 // This... may seems surprising, and justifiably so. On 32-bit MSVC the
227266 // pointers between these structure are just that, pointers. On 64-bit MSVC,
@@ -243,6 +282,12 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
243282 //
244283 // In any case, we basically need to do something like this until we can
245284 // express more operations in statics (and we may never be able to).
285+ if !cfg ! ( bootstrap) {
286+ atomic_store (
287+ & mut THROW_INFO . pmfnUnwind as * mut _ as * mut u32 ,
288+ ptr ! ( exception_cleanup) as u32 ,
289+ ) ;
290+ }
246291 atomic_store (
247292 & mut THROW_INFO . pCatchableTypeArray as * mut _ as * mut u32 ,
248293 ptr ! ( & CATCHABLE_TYPE_ARRAY as * const _) as u32 ,
@@ -255,6 +300,12 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
255300 & mut CATCHABLE_TYPE . pType as * mut _ as * mut u32 ,
256301 ptr ! ( & TYPE_DESCRIPTOR as * const _) as u32 ,
257302 ) ;
303+ if !cfg ! ( bootstrap) {
304+ atomic_store (
305+ & mut CATCHABLE_TYPE . copyFunction as * mut _ as * mut u32 ,
306+ ptr ! ( exception_copy) as u32 ,
307+ ) ;
308+ }
258309
259310 extern "system" {
260311 #[ unwind( allowed) ]
0 commit comments