1
1
use crate :: ich:: StableHashingContext ;
2
+ use crate :: middle:: codegen_fn_attrs:: CodegenFnAttrFlags ;
2
3
use crate :: mir:: { GeneratorLayout , GeneratorSavedLocal } ;
3
4
use crate :: ty:: subst:: Subst ;
4
5
use crate :: ty:: { self , subst:: SubstsRef , ReprOptions , Ty , TyCtxt , TypeFoldable } ;
@@ -15,7 +16,7 @@ use rustc_target::abi::call::{
15
16
ArgAbi , ArgAttribute , ArgAttributes , Conv , FnAbi , PassMode , Reg , RegKind ,
16
17
} ;
17
18
pub use rustc_target:: abi:: * ;
18
- use rustc_target:: spec:: { abi:: Abi as SpecAbi , HasTargetSpec } ;
19
+ use rustc_target:: spec:: { abi:: Abi as SpecAbi , HasTargetSpec , PanicStrategy } ;
19
20
20
21
use std:: cmp;
21
22
use std:: fmt;
@@ -2368,11 +2369,55 @@ where
2368
2369
sig : ty:: PolyFnSig < ' tcx > ,
2369
2370
extra_args : & [ Ty < ' tcx > ] ,
2370
2371
caller_location : Option < Ty < ' tcx > > ,
2372
+ codegen_fn_attr_flags : CodegenFnAttrFlags ,
2371
2373
mk_arg_type : impl Fn ( Ty < ' tcx > , Option < usize > ) -> ArgAbi < ' tcx , Ty < ' tcx > > ,
2372
2374
) -> Self ;
2373
2375
fn adjust_for_abi ( & mut self , cx : & C , abi : SpecAbi ) ;
2374
2376
}
2375
2377
2378
+ fn fn_can_unwind (
2379
+ panic_strategy : PanicStrategy ,
2380
+ codegen_fn_attr_flags : CodegenFnAttrFlags ,
2381
+ call_conv : Conv ,
2382
+ ) -> bool {
2383
+ if panic_strategy != PanicStrategy :: Unwind {
2384
+ // In panic=abort mode we assume nothing can unwind anywhere, so
2385
+ // optimize based on this!
2386
+ false
2387
+ } else if codegen_fn_attr_flags. contains ( CodegenFnAttrFlags :: UNWIND ) {
2388
+ // If a specific #[unwind] attribute is present, use that.
2389
+ true
2390
+ } else if codegen_fn_attr_flags. contains ( CodegenFnAttrFlags :: RUSTC_ALLOCATOR_NOUNWIND ) {
2391
+ // Special attribute for allocator functions, which can't unwind.
2392
+ false
2393
+ } else {
2394
+ if call_conv == Conv :: Rust {
2395
+ // Any Rust method (or `extern "Rust" fn` or `extern
2396
+ // "rust-call" fn`) is explicitly allowed to unwind
2397
+ // (unless it has no-unwind attribute, handled above).
2398
+ true
2399
+ } else {
2400
+ // Anything else is either:
2401
+ //
2402
+ // 1. A foreign item using a non-Rust ABI (like `extern "C" { fn foo(); }`), or
2403
+ //
2404
+ // 2. A Rust item using a non-Rust ABI (like `extern "C" fn foo() { ... }`).
2405
+ //
2406
+ // Foreign items (case 1) are assumed to not unwind; it is
2407
+ // UB otherwise. (At least for now; see also
2408
+ // rust-lang/rust#63909 and Rust RFC 2753.)
2409
+ //
2410
+ // Items defined in Rust with non-Rust ABIs (case 2) are also
2411
+ // not supposed to unwind. Whether this should be enforced
2412
+ // (versus stating it is UB) and *how* it would be enforced
2413
+ // is currently under discussion; see rust-lang/rust#58794.
2414
+ //
2415
+ // In either case, we mark item as explicitly nounwind.
2416
+ false
2417
+ }
2418
+ }
2419
+ }
2420
+
2376
2421
impl < ' tcx , C > FnAbiExt < ' tcx , C > for call:: FnAbi < ' tcx , Ty < ' tcx > >
2377
2422
where
2378
2423
C : LayoutOf < Ty = Ty < ' tcx > , TyAndLayout = TyAndLayout < ' tcx > >
@@ -2382,7 +2427,12 @@ where
2382
2427
+ HasParamEnv < ' tcx > ,
2383
2428
{
2384
2429
fn of_fn_ptr ( cx : & C , sig : ty:: PolyFnSig < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self {
2385
- call:: FnAbi :: new_internal ( cx, sig, extra_args, None , |ty, _| ArgAbi :: new ( cx. layout_of ( ty) ) )
2430
+ // Assume that fn pointers may always unwind
2431
+ let codegen_fn_attr_flags = CodegenFnAttrFlags :: UNWIND ;
2432
+
2433
+ call:: FnAbi :: new_internal ( cx, sig, extra_args, None , codegen_fn_attr_flags, |ty, _| {
2434
+ ArgAbi :: new ( cx. layout_of ( ty) )
2435
+ } )
2386
2436
}
2387
2437
2388
2438
fn of_instance ( cx : & C , instance : ty:: Instance < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self {
@@ -2394,7 +2444,9 @@ where
2394
2444
None
2395
2445
} ;
2396
2446
2397
- call:: FnAbi :: new_internal ( cx, sig, extra_args, caller_location, |ty, arg_idx| {
2447
+ let attrs = cx. tcx ( ) . codegen_fn_attrs ( instance. def_id ( ) ) . flags ;
2448
+
2449
+ call:: FnAbi :: new_internal ( cx, sig, extra_args, caller_location, attrs, |ty, arg_idx| {
2398
2450
let mut layout = cx. layout_of ( ty) ;
2399
2451
// Don't pass the vtable, it's not an argument of the virtual fn.
2400
2452
// Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
@@ -2450,6 +2502,7 @@ where
2450
2502
sig : ty:: PolyFnSig < ' tcx > ,
2451
2503
extra_args : & [ Ty < ' tcx > ] ,
2452
2504
caller_location : Option < Ty < ' tcx > > ,
2505
+ codegen_fn_attr_flags : CodegenFnAttrFlags ,
2453
2506
mk_arg_type : impl Fn ( Ty < ' tcx > , Option < usize > ) -> ArgAbi < ' tcx , Ty < ' tcx > > ,
2454
2507
) -> Self {
2455
2508
debug ! ( "FnAbi::new_internal({:?}, {:?})" , sig, extra_args) ;
@@ -2639,6 +2692,7 @@ where
2639
2692
c_variadic : sig. c_variadic ,
2640
2693
fixed_count : inputs. len ( ) ,
2641
2694
conv,
2695
+ can_unwind : fn_can_unwind ( cx. tcx ( ) . sess . panic_strategy ( ) , codegen_fn_attr_flags, conv) ,
2642
2696
} ;
2643
2697
fn_abi. adjust_for_abi ( cx, sig. abi ) ;
2644
2698
fn_abi
0 commit comments