@@ -17,7 +17,7 @@ use super::{
17
17
} ;
18
18
19
19
impl < ' mir , ' tcx : ' mir , M : Machine < ' mir , ' tcx > > InterpCx < ' mir , ' tcx , M > {
20
- pub ( super ) fn fn_can_unwind ( & self , attrs : CodegenFnAttrFlags , abi : Abi ) -> bool {
20
+ fn fn_can_unwind ( & self , attrs : CodegenFnAttrFlags , abi : Abi ) -> bool {
21
21
layout:: fn_can_unwind (
22
22
self . tcx . sess . panic_strategy ( ) ,
23
23
attrs,
@@ -247,37 +247,38 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
247
247
}
248
248
} ;
249
249
250
+ let get_abi = |this : & Self , instance_ty : Ty < ' tcx > | match instance_ty. kind ( ) {
251
+ ty:: FnDef ( ..) => instance_ty. fn_sig ( * this. tcx ) . abi ( ) ,
252
+ ty:: Closure ( ..) => Abi :: RustCall ,
253
+ ty:: Generator ( ..) => Abi :: Rust ,
254
+ _ => span_bug ! ( this. cur_span( ) , "unexpected callee ty: {:?}" , instance_ty) ,
255
+ } ;
256
+
250
257
// ABI check
251
- let check_abi = |this : & Self , instance_ty : Ty < ' tcx > | -> InterpResult < ' tcx > {
252
- if M :: enforce_abi ( this) {
253
- let callee_abi = match instance_ty. kind ( ) {
254
- ty:: FnDef ( ..) => instance_ty. fn_sig ( * this. tcx ) . abi ( ) ,
255
- ty:: Closure ( ..) => Abi :: RustCall ,
256
- ty:: Generator ( ..) => Abi :: Rust ,
257
- _ => span_bug ! ( this. cur_span( ) , "unexpected callee ty: {:?}" , instance_ty) ,
258
- } ;
259
- let normalize_abi = |abi| match abi {
260
- Abi :: Rust | Abi :: RustCall | Abi :: RustIntrinsic | Abi :: PlatformIntrinsic =>
261
- // These are all the same ABI, really.
262
- {
263
- Abi :: Rust
264
- }
265
- abi => abi,
266
- } ;
267
- if normalize_abi ( caller_abi) != normalize_abi ( callee_abi) {
268
- throw_ub_format ! (
269
- "calling a function with ABI {} using caller ABI {}" ,
270
- callee_abi. name( ) ,
271
- caller_abi. name( )
272
- )
258
+ let check_abi = |callee_abi : Abi | -> InterpResult < ' tcx > {
259
+ let normalize_abi = |abi| match abi {
260
+ Abi :: Rust | Abi :: RustCall | Abi :: RustIntrinsic | Abi :: PlatformIntrinsic =>
261
+ // These are all the same ABI, really.
262
+ {
263
+ Abi :: Rust
273
264
}
265
+ abi => abi,
266
+ } ;
267
+ if normalize_abi ( caller_abi) != normalize_abi ( callee_abi) {
268
+ throw_ub_format ! (
269
+ "calling a function with ABI {} using caller ABI {}" ,
270
+ callee_abi. name( ) ,
271
+ caller_abi. name( )
272
+ )
274
273
}
275
274
Ok ( ( ) )
276
275
} ;
277
276
278
277
match instance. def {
279
278
ty:: InstanceDef :: Intrinsic ( ..) => {
280
- check_abi ( self , instance. ty ( * self . tcx , self . param_env ) ) ?;
279
+ if M :: enforce_abi ( self ) {
280
+ check_abi ( get_abi ( self , instance. ty ( * self . tcx , self . param_env ) ) ) ?;
281
+ }
281
282
assert ! ( caller_abi == Abi :: RustIntrinsic || caller_abi == Abi :: PlatformIntrinsic ) ;
282
283
M :: call_intrinsic ( self , instance, args, ret, unwind)
283
284
}
@@ -298,15 +299,23 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
298
299
// Check against the ABI of the MIR body we are calling (not the ABI of `instance`;
299
300
// these can differ when `find_mir_or_eval_fn` does something clever like resolve
300
301
// exported symbol names).
301
- check_abi ( self , self . tcx . type_of ( body. source . def_id ( ) ) ) ?;
302
+ let callee_def_id = body. source . def_id ( ) ;
303
+ let callee_abi = get_abi ( self , self . tcx . type_of ( callee_def_id) ) ;
304
+
305
+ if M :: enforce_abi ( self ) {
306
+ check_abi ( callee_abi) ?;
307
+ }
308
+
309
+ let callee_can_unwind =
310
+ self . fn_can_unwind ( self . tcx . codegen_fn_attrs ( callee_def_id) . flags , callee_abi) ;
302
311
303
312
self . push_stack_frame (
304
313
instance,
305
314
body,
306
315
ret. map ( |p| p. 0 ) ,
307
316
StackPopCleanup :: Goto {
308
317
ret : ret. map ( |p| p. 1 ) ,
309
- unwind : if can_unwind {
318
+ unwind : if can_unwind && callee_can_unwind {
310
319
StackPopUnwind :: Cleanup ( unwind)
311
320
} else {
312
321
StackPopUnwind :: NotAllowed
0 commit comments