File tree Expand file tree Collapse file tree 3 files changed +22
-19
lines changed Expand file tree Collapse file tree 3 files changed +22
-19
lines changed Original file line number Diff line number Diff line change @@ -53,6 +53,10 @@ pub fn payload() -> *mut u8 {
5353}
5454
5555struct Exception {
56+ // This needs to be an Option because the object's lifetime follows C++
57+ // semantics: when catch_unwind moves the Box out of the exception it must
58+ // still leave the exception object in a valid state because its destructor
59+ // is still going to be called by __cxa_end_catch..
5660 data : Option < Box < dyn Any + Send > > ,
5761}
5862
Original file line number Diff line number Diff line change @@ -224,33 +224,28 @@ static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor {
224224// used as the result of the exception copy. This is used by the C++ runtime to
225225// support capturing exceptions with std::exception_ptr, which we can't support
226226// because Box<dyn Any> isn't clonable.
227- cfg_if:: cfg_if! {
228- if #[ cfg( target_arch = "x86" ) ] {
229- unsafe extern "thiscall" fn exception_cleanup( e: * mut [ u64 ; 2 ] ) {
230- if ( * e) [ 0 ] != 0 {
231- cleanup( * e) ;
232- }
233- }
234- #[ unwind( allowed) ]
235- unsafe extern "thiscall" 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- } else {
241- unsafe extern "C" fn exception_cleanup( e: * mut [ u64 ; 2 ] ) {
227+ macro_rules! define_cleanup {
228+ ( $abi: tt) => {
229+ unsafe extern $abi fn exception_cleanup( e: * mut [ u64 ; 2 ] ) {
242230 if ( * e) [ 0 ] != 0 {
243231 cleanup( * e) ;
244232 }
245233 }
246234 #[ unwind( allowed) ]
247- unsafe extern "C" fn exception_copy( _dest: * mut [ u64 ; 2 ] ,
248- _src: * mut [ u64 ; 2 ] )
249- -> * mut [ u64 ; 2 ] {
235+ unsafe extern $abi fn exception_copy( _dest: * mut [ u64 ; 2 ] ,
236+ _src: * mut [ u64 ; 2 ] )
237+ -> * mut [ u64 ; 2 ] {
250238 panic!( "Rust panics cannot be copied" ) ;
251239 }
252240 }
253241}
242+ cfg_if:: cfg_if! {
243+ if #[ cfg( target_arch = "x86" ) ] {
244+ define_cleanup!( "thiscall" ) ;
245+ } else {
246+ define_cleanup!( "C" ) ;
247+ }
248+ }
254249
255250pub unsafe fn panic ( data : Box < dyn Any + Send > ) -> u32 {
256251 use core:: intrinsics:: atomic_store;
Original file line number Diff line number Diff line change @@ -953,7 +953,9 @@ fn codegen_msvc_try(
953953 catchswitch. add_handler ( cs, catchpad. llbb ( ) ) ;
954954
955955 // The flag value of 8 indicates that we are catching the exception by
956- // reference instead of by value.
956+ // reference instead of by value. We can't use catch by value because
957+ // that requires copying the exception object, which we don't support
958+ // since our exception object effectively contains a Box.
957959 //
958960 // Source: MicrosoftCXXABI::getAddrOfCXXCatchHandlerType in clang
959961 let flags = bx. const_i32 ( 8 ) ;
@@ -970,6 +972,8 @@ fn codegen_msvc_try(
970972 catchpad. store ( payload, local_ptr, i64_align) ;
971973
972974 // Clear the first word of the exception so avoid double-dropping it.
975+ // This will be read by the destructor which is implicitly called at the
976+ // end of the catch block by the runtime.
973977 let payload_0_ptr = catchpad. inbounds_gep ( payload_ptr, & [ bx. const_i32 ( 0 ) , bx. const_i32 ( 0 ) ] ) ;
974978 catchpad. store ( bx. const_u64 ( 0 ) , payload_0_ptr, i64_align) ;
975979
You can’t perform that action at this time.
0 commit comments