@@ -15,14 +15,15 @@ use rustc::hir::{CodegenFnAttrFlags, CodegenFnAttrs};
15
15
use rustc:: hir:: def_id:: { DefId , LOCAL_CRATE } ;
16
16
use rustc:: session:: Session ;
17
17
use rustc:: session:: config:: Sanitizer ;
18
- use rustc:: ty:: TyCtxt ;
18
+ use rustc:: ty:: { self , TyCtxt , PolyFnSig } ;
19
19
use rustc:: ty:: layout:: HasTyCtxt ;
20
20
use rustc:: ty:: query:: Providers ;
21
21
use rustc_data_structures:: sync:: Lrc ;
22
22
use rustc_data_structures:: fx:: FxHashMap ;
23
23
use rustc_target:: spec:: PanicStrategy ;
24
24
use rustc_codegen_ssa:: traits:: * ;
25
25
26
+ use abi:: Abi ;
26
27
use attributes;
27
28
use llvm:: { self , Attribute } ;
28
29
use llvm:: AttributePlace :: Function ;
@@ -60,7 +61,7 @@ pub fn emit_uwtable(val: &'ll Value, emit: bool) {
60
61
61
62
/// Tell LLVM whether the function can or cannot unwind.
62
63
#[ inline]
63
- pub fn unwind ( val : & ' ll Value , can_unwind : bool ) {
64
+ fn unwind ( val : & ' ll Value , can_unwind : bool ) {
64
65
Attribute :: NoUnwind . toggle_llfn ( Function , val, !can_unwind) ;
65
66
}
66
67
@@ -150,9 +151,10 @@ pub fn non_lazy_bind(sess: &Session, llfn: &'ll Value) {
150
151
/// Composite function which sets LLVM attributes for function depending on its AST (`#[attribute]`)
151
152
/// attributes.
152
153
pub fn from_fn_attrs (
153
- cx : & CodegenCx < ' ll , ' _ > ,
154
+ cx : & CodegenCx < ' ll , ' tcx > ,
154
155
llfn : & ' ll Value ,
155
156
id : Option < DefId > ,
157
+ sig : PolyFnSig < ' tcx > ,
156
158
) {
157
159
let codegen_fn_attrs = id. map ( |id| cx. tcx . codegen_fn_attrs ( id) )
158
160
. unwrap_or_else ( || CodegenFnAttrs :: new ( ) ) ;
@@ -194,28 +196,37 @@ pub fn from_fn_attrs(
194
196
llvm:: AttributePlace :: ReturnValue , llfn) ;
195
197
}
196
198
197
- let can_unwind = if codegen_fn_attrs. flags . contains ( CodegenFnAttrFlags :: UNWIND ) {
198
- Some ( true )
199
+ unwind ( llfn, if cx. tcx . sess . panic_strategy ( ) != PanicStrategy :: Unwind {
200
+ // In panic=abort mode we assume nothing can unwind anywhere, so
201
+ // optimize based on this!
202
+ false
203
+ } else if codegen_fn_attrs. flags . contains ( CodegenFnAttrFlags :: UNWIND ) {
204
+ // If a specific #[unwind] attribute is present, use that
205
+ true
199
206
} else if codegen_fn_attrs. flags . contains ( CodegenFnAttrFlags :: RUSTC_ALLOCATOR_NOUNWIND ) {
200
- Some ( false )
201
-
202
- // Perhaps questionable, but we assume that anything defined
203
- // *in Rust code* may unwind. Foreign items like `extern "C" {
204
- // fn foo(); }` are assumed not to unwind **unless** they have
205
- // a `#[unwind]` attribute.
206
- } else if id. map ( |id| !cx. tcx . is_foreign_item ( id) ) . unwrap_or ( false ) {
207
- Some ( true )
208
- } else {
209
- None
210
- } ;
211
-
212
- match can_unwind {
213
- Some ( false ) => attributes:: unwind ( llfn, false ) ,
214
- Some ( true ) if cx. tcx . sess . panic_strategy ( ) == PanicStrategy :: Unwind => {
215
- attributes:: unwind ( llfn, true ) ;
207
+ // Special attribute for allocator functions, which can't unwind
208
+ false
209
+ } else if let Some ( id) = id {
210
+ let sig = cx. tcx . normalize_erasing_late_bound_regions ( ty:: ParamEnv :: reveal_all ( ) , & sig) ;
211
+ if cx. tcx . is_foreign_item ( id) {
212
+ // Foreign items like `extern "C" { fn foo(); }` are assumed not to
213
+ // unwind
214
+ false
215
+ } else if sig. abi != Abi :: Rust && sig. abi != Abi :: RustCall {
216
+ // Any items defined in Rust that *don't* have the `extern` ABI are
217
+ // defined to not unwind. We insert shims to abort if an unwind
218
+ // happens to enforce this.
219
+ false
220
+ } else {
221
+ // Anything else defined in Rust is assumed that it can possibly
222
+ // unwind
223
+ true
216
224
}
217
- Some ( true ) | None => { }
218
- }
225
+ } else {
226
+ // assume this can possibly unwind, avoiding the application of a
227
+ // `nounwind` attribute below.
228
+ true
229
+ } ) ;
219
230
220
231
// Always annotate functions with the target-cpu they are compiled for.
221
232
// Without this, ThinLTO won't inline Rust functions into Clang generated
0 commit comments