@@ -27,8 +27,8 @@ use rustc_hir::def_id::LocalDefId;
27
27
use rustc_index:: IndexVec ;
28
28
use rustc_middle:: mir:: {
29
29
AnalysisPhase , Body , CallSource , ClearCrossCrate , ConstOperand , ConstQualifs , LocalDecl ,
30
- MirPhase , Operand , Place , ProjectionElem , Promoted , RuntimePhase , Rvalue , START_BLOCK ,
31
- SourceInfo , Statement , StatementKind , TerminatorKind ,
30
+ MirFlags , MirPhase , Operand , Place , ProjectionElem , Promoted , RuntimePhase , Rvalue ,
31
+ START_BLOCK , SourceInfo , Statement , StatementKind , TerminatorKind ,
32
32
} ;
33
33
use rustc_middle:: ty:: { self , TyCtxt , TypeVisitableExt } ;
34
34
use rustc_middle:: util:: Providers ;
@@ -135,6 +135,7 @@ pub fn provide(providers: &mut Providers) {
135
135
promoted_mir,
136
136
deduced_param_attrs : deduce_param_attrs:: deduced_param_attrs,
137
137
coroutine_by_move_body_def_id : coroutine:: coroutine_by_move_body_def_id,
138
+ mir_flags,
138
139
..providers. queries
139
140
} ;
140
141
}
@@ -331,14 +332,15 @@ fn mir_promoted(
331
332
_ => ConstQualifs :: default ( ) ,
332
333
} ;
333
334
334
- // the `has_ffi_unwind_calls` query uses the raw mir, so make sure it is run.
335
- tcx. ensure_with_value ( ) . has_ffi_unwind_calls ( def) ;
335
+ tcx. ensure_with_value ( ) . mir_flags ( def) ;
336
336
337
337
// the `by_move_body` query uses the raw mir, so make sure it is run.
338
338
if tcx. needs_coroutine_by_move_body_def_id ( def. to_def_id ( ) ) {
339
339
tcx. ensure_with_value ( ) . coroutine_by_move_body_def_id ( def) ;
340
340
}
341
341
342
+ tcx. ensure_with_value ( ) . mir_flags ( def) ;
343
+
342
344
let mut body = tcx. mir_built ( def) . steal ( ) ;
343
345
if let Some ( error_reported) = const_qualifs. tainted_by_errors {
344
346
body. tainted_by_errors = Some ( error_reported) ;
@@ -361,6 +363,33 @@ fn mir_promoted(
361
363
( tcx. alloc_steal_mir ( body) , tcx. alloc_steal_promoted ( promoted) )
362
364
}
363
365
366
+ fn mir_flags < ' tcx > ( tcx : TyCtxt < ' tcx > , local_def_id : LocalDefId ) -> MirFlags {
367
+ let mut flags = MirFlags :: default ( ) ;
368
+ if !tcx. is_mir_available ( local_def_id) {
369
+ return flags;
370
+ }
371
+
372
+ // Only perform check on functions because constants cannot call FFI functions.
373
+ let kind = tcx. def_kind ( local_def_id) ;
374
+ if !kind. is_fn_like ( ) {
375
+ return flags;
376
+ }
377
+
378
+ let body = & * tcx. mir_built ( local_def_id) . borrow ( ) ;
379
+
380
+ if is_nounwind ( body) {
381
+ flags. insert ( MirFlags :: IS_NOUNWIND ) ;
382
+ }
383
+ if ffi_unwind_calls:: has_ffi_unwind_calls ( tcx, body) {
384
+ flags. insert ( MirFlags :: HAS_FFI_UNWIND_CALLS ) ;
385
+ }
386
+ flags
387
+ }
388
+
389
+ fn is_nounwind < ' tcx > ( body : & Body < ' tcx > ) -> bool {
390
+ body. basic_blocks . iter ( ) . all ( |block| block. terminator ( ) . unwind ( ) . is_none ( ) )
391
+ }
392
+
364
393
/// Compute the MIR that is used during CTFE (and thus has no optimizations run on it)
365
394
fn mir_for_ctfe ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) -> & Body < ' _ > {
366
395
tcx. arena . alloc ( inner_mir_for_ctfe ( tcx, def_id) )
0 commit comments