File tree 3 files changed +22
-19
lines changed
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 {
53
53
}
54
54
55
55
struct 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..
56
60
data : Option < Box < dyn Any + Send > > ,
57
61
}
58
62
Original file line number Diff line number Diff line change @@ -224,33 +224,28 @@ static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor {
224
224
// used as the result of the exception copy. This is used by the C++ runtime to
225
225
// support capturing exceptions with std::exception_ptr, which we can't support
226
226
// 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 ] ) {
242
230
if ( * e) [ 0 ] != 0 {
243
231
cleanup( * e) ;
244
232
}
245
233
}
246
234
#[ 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 ] {
250
238
panic!( "Rust panics cannot be copied" ) ;
251
239
}
252
240
}
253
241
}
242
+ cfg_if:: cfg_if! {
243
+ if #[ cfg( target_arch = "x86" ) ] {
244
+ define_cleanup!( "thiscall" ) ;
245
+ } else {
246
+ define_cleanup!( "C" ) ;
247
+ }
248
+ }
254
249
255
250
pub unsafe fn panic ( data : Box < dyn Any + Send > ) -> u32 {
256
251
use core:: intrinsics:: atomic_store;
Original file line number Diff line number Diff line change @@ -953,7 +953,9 @@ fn codegen_msvc_try(
953
953
catchswitch. add_handler ( cs, catchpad. llbb ( ) ) ;
954
954
955
955
// 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.
957
959
//
958
960
// Source: MicrosoftCXXABI::getAddrOfCXXCatchHandlerType in clang
959
961
let flags = bx. const_i32 ( 8 ) ;
@@ -970,6 +972,8 @@ fn codegen_msvc_try(
970
972
catchpad. store ( payload, local_ptr, i64_align) ;
971
973
972
974
// 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.
973
977
let payload_0_ptr = catchpad. inbounds_gep ( payload_ptr, & [ bx. const_i32 ( 0 ) , bx. const_i32 ( 0 ) ] ) ;
974
978
catchpad. store ( bx. const_u64 ( 0 ) , payload_0_ptr, i64_align) ;
975
979
You can’t perform that action at this time.
0 commit comments