11use crate :: ich:: StableHashingContext ;
2+ use crate :: middle:: codegen_fn_attrs:: CodegenFnAttrFlags ;
23use crate :: mir:: { GeneratorLayout , GeneratorSavedLocal } ;
34use crate :: ty:: subst:: Subst ;
45use crate :: ty:: { self , subst:: SubstsRef , ReprOptions , Ty , TyCtxt , TypeFoldable } ;
@@ -15,7 +16,7 @@ use rustc_target::abi::call::{
1516 ArgAbi , ArgAttribute , ArgAttributes , Conv , FnAbi , PassMode , Reg , RegKind ,
1617} ;
1718pub 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 } ;
1920
2021use std:: cmp;
2122use std:: fmt;
@@ -2368,11 +2369,55 @@ where
23682369 sig : ty:: PolyFnSig < ' tcx > ,
23692370 extra_args : & [ Ty < ' tcx > ] ,
23702371 caller_location : Option < Ty < ' tcx > > ,
2372+ codegen_fn_attr_flags : CodegenFnAttrFlags ,
23712373 mk_arg_type : impl Fn ( Ty < ' tcx > , Option < usize > ) -> ArgAbi < ' tcx , Ty < ' tcx > > ,
23722374 ) -> Self ;
23732375 fn adjust_for_abi ( & mut self , cx : & C , abi : SpecAbi ) ;
23742376}
23752377
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+
23762421impl < ' tcx , C > FnAbiExt < ' tcx , C > for call:: FnAbi < ' tcx , Ty < ' tcx > >
23772422where
23782423 C : LayoutOf < Ty = Ty < ' tcx > , TyAndLayout = TyAndLayout < ' tcx > >
@@ -2382,7 +2427,12 @@ where
23822427 + HasParamEnv < ' tcx > ,
23832428{
23842429 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+ } )
23862436 }
23872437
23882438 fn of_instance ( cx : & C , instance : ty:: Instance < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self {
@@ -2394,7 +2444,9 @@ where
23942444 None
23952445 } ;
23962446
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| {
23982450 let mut layout = cx. layout_of ( ty) ;
23992451 // Don't pass the vtable, it's not an argument of the virtual fn.
24002452 // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
@@ -2450,6 +2502,7 @@ where
24502502 sig : ty:: PolyFnSig < ' tcx > ,
24512503 extra_args : & [ Ty < ' tcx > ] ,
24522504 caller_location : Option < Ty < ' tcx > > ,
2505+ codegen_fn_attr_flags : CodegenFnAttrFlags ,
24532506 mk_arg_type : impl Fn ( Ty < ' tcx > , Option < usize > ) -> ArgAbi < ' tcx , Ty < ' tcx > > ,
24542507 ) -> Self {
24552508 debug ! ( "FnAbi::new_internal({:?}, {:?})" , sig, extra_args) ;
@@ -2639,6 +2692,7 @@ where
26392692 c_variadic : sig. c_variadic ,
26402693 fixed_count : inputs. len ( ) ,
26412694 conv,
2695+ can_unwind : fn_can_unwind ( cx. tcx ( ) . sess . panic_strategy ( ) , codegen_fn_attr_flags, conv) ,
26422696 } ;
26432697 fn_abi. adjust_for_abi ( cx, sig. abi ) ;
26442698 fn_abi
0 commit comments