@@ -77,8 +77,11 @@ use libc::{c_int, c_uint, c_void};
77
77
// #include <stdint.h>
78
78
//
79
79
// struct rust_panic {
80
+ // rust_panic(const rust_panic&);
81
+ // ~rust_panic();
82
+ //
80
83
// uint64_t x[2];
81
- // }
84
+ // };
82
85
//
83
86
// void foo() {
84
87
// rust_panic a = {0, 1};
@@ -128,7 +131,7 @@ mod imp {
128
131
#[ repr( C ) ]
129
132
pub struct _ThrowInfo {
130
133
pub attributes : c_uint ,
131
- pub pnfnUnwind : imp:: ptr_t ,
134
+ pub pmfnUnwind : imp:: ptr_t ,
132
135
pub pForwardCompat : imp:: ptr_t ,
133
136
pub pCatchableTypeArray : imp:: ptr_t ,
134
137
}
@@ -145,7 +148,7 @@ pub struct _CatchableType {
145
148
pub pType : imp:: ptr_t ,
146
149
pub thisDisplacement : _PMD ,
147
150
pub sizeOrOffset : c_int ,
148
- pub copy_function : imp:: ptr_t ,
151
+ pub copyFunction : imp:: ptr_t ,
149
152
}
150
153
151
154
#[ repr( C ) ]
@@ -168,7 +171,7 @@ const TYPE_NAME: [u8; 11] = *b"rust_panic\0";
168
171
169
172
static mut THROW_INFO : _ThrowInfo = _ThrowInfo {
170
173
attributes : 0 ,
171
- pnfnUnwind : ptr ! ( 0 ) ,
174
+ pmfnUnwind : ptr ! ( 0 ) ,
172
175
pForwardCompat : ptr ! ( 0 ) ,
173
176
pCatchableTypeArray : ptr ! ( 0 ) ,
174
177
} ;
@@ -181,7 +184,7 @@ static mut CATCHABLE_TYPE: _CatchableType = _CatchableType {
181
184
pType : ptr ! ( 0 ) ,
182
185
thisDisplacement : _PMD { mdisp : 0 , pdisp : -1 , vdisp : 0 } ,
183
186
sizeOrOffset : mem:: size_of :: < [ u64 ; 2 ] > ( ) as c_int ,
184
- copy_function : ptr ! ( 0 ) ,
187
+ copyFunction : ptr ! ( 0 ) ,
185
188
} ;
186
189
187
190
extern "C" {
@@ -208,6 +211,43 @@ static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor {
208
211
name : TYPE_NAME ,
209
212
} ;
210
213
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
+
211
251
pub unsafe fn panic ( data : Box < dyn Any + Send > ) -> u32 {
212
252
use core:: intrinsics:: atomic_store;
213
253
@@ -220,8 +260,7 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
220
260
// exception (constructed above).
221
261
let ptrs = mem:: transmute :: < _ , raw:: TraitObject > ( data) ;
222
262
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 _ ;
225
264
226
265
// This... may seems surprising, and justifiably so. On 32-bit MSVC the
227
266
// 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 {
243
282
//
244
283
// In any case, we basically need to do something like this until we can
245
284
// 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
+ }
246
291
atomic_store (
247
292
& mut THROW_INFO . pCatchableTypeArray as * mut _ as * mut u32 ,
248
293
ptr ! ( & CATCHABLE_TYPE_ARRAY as * const _) as u32 ,
@@ -255,6 +300,12 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
255
300
& mut CATCHABLE_TYPE . pType as * mut _ as * mut u32 ,
256
301
ptr ! ( & TYPE_DESCRIPTOR as * const _) as u32 ,
257
302
) ;
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
+ }
258
309
259
310
extern "system" {
260
311
#[ unwind( allowed) ]
0 commit comments