Skip to content

Commit 30bc5a9

Browse files
committed
Move abort_unwinding_calls earlier
1 parent 1c07096 commit 30bc5a9

File tree

2 files changed

+54
-26
lines changed

2 files changed

+54
-26
lines changed

compiler/rustc_mir/src/transform/abort_unwinding_calls.rs

Lines changed: 50 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::transform::MirPass;
2+
use rustc_hir::def::DefKind;
23
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
34
use rustc_middle::mir::*;
45
use rustc_middle::ty::layout;
@@ -24,15 +25,28 @@ pub struct AbortUnwindingCalls;
2425

2526
impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
2627
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
28+
let def_id = body.source.def_id();
29+
let kind = tcx.def_kind(def_id);
30+
31+
// We don't simplify the MIR of constants at this time because that
32+
// namely results in a cyclic query when we call `tcx.type_of` below.
33+
let is_function = match kind {
34+
DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) => true,
35+
_ => tcx.is_closure(def_id),
36+
};
37+
if !is_function {
38+
return;
39+
}
40+
2741
// This pass only runs on functions which themselves cannot unwind,
2842
// forcibly changing the body of the function to structurally provide
2943
// this guarantee by aborting on an unwind. If this function can unwind,
3044
// then there's nothing to do because it already should work correctly.
3145
//
3246
// Here we test for this function itself whether its ABI allows
3347
// unwinding or not.
34-
let body_flags = tcx.codegen_fn_attrs(body.source.def_id()).flags;
35-
let body_ty = tcx.type_of(body.source.def_id());
48+
let body_flags = tcx.codegen_fn_attrs(def_id).flags;
49+
let body_ty = tcx.type_of(def_id);
3650
let body_abi = match body_ty.kind() {
3751
ty::FnDef(..) => body_ty.fn_sig(tcx).abi(),
3852
ty::Closure(..) => Abi::RustCall,
@@ -51,22 +65,31 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
5165
if block.is_cleanup {
5266
continue;
5367
}
68+
let terminator = match &block.terminator {
69+
Some(terminator) => terminator,
70+
None => continue,
71+
};
72+
let span = terminator.source_info.span;
5473

55-
let (func, source_info) = match &block.terminator {
56-
Some(Terminator { kind: TerminatorKind::Call { func, .. }, source_info }) => {
57-
(func, source_info)
74+
let call_can_unwind = match &terminator.kind {
75+
TerminatorKind::Call { func, .. } => {
76+
let ty = func.ty(body, tcx);
77+
let sig = ty.fn_sig(tcx);
78+
let flags = match ty.kind() {
79+
ty::FnPtr(_) => CodegenFnAttrFlags::empty(),
80+
ty::FnDef(def_id, _) => tcx.codegen_fn_attrs(*def_id).flags,
81+
_ => span_bug!(span, "invalid callee of type {:?}", ty),
82+
};
83+
layout::fn_can_unwind(tcx, flags, sig.abi())
84+
}
85+
TerminatorKind::Drop { .. }
86+
| TerminatorKind::DropAndReplace { .. }
87+
| TerminatorKind::Assert { .. }
88+
| TerminatorKind::FalseUnwind { .. } => {
89+
layout::fn_can_unwind(tcx, CodegenFnAttrFlags::empty(), Abi::Rust)
5890
}
5991
_ => continue,
6092
};
61-
let ty = func.ty(body, tcx);
62-
let sig = ty.fn_sig(tcx);
63-
let flags = match ty.kind() {
64-
ty::FnPtr(_) => CodegenFnAttrFlags::empty(),
65-
ty::FnDef(def_id, _) => tcx.codegen_fn_attrs(*def_id).flags,
66-
_ => span_bug!(source_info.span, "invalid callee of type {:?}", ty),
67-
};
68-
69-
let call_can_unwind = layout::fn_can_unwind(tcx, flags, sig.abi());
7093

7194
// If this function call can't unwind, then there's no need for it
7295
// to have a landing pad. This means that we can remove any cleanup
@@ -102,23 +125,28 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
102125
let abort_bb = body.basic_blocks_mut().push(bb);
103126

104127
for bb in calls_to_terminate {
105-
let cleanup = match &mut body.basic_blocks_mut()[bb].terminator {
106-
Some(Terminator { kind: TerminatorKind::Call { cleanup, .. }, .. }) => cleanup,
107-
_ => unreachable!(),
108-
};
128+
let cleanup = get_cleanup(body.basic_blocks_mut()[bb].terminator_mut());
109129
*cleanup = Some(abort_bb);
110130
}
111131
}
112132

113133
for id in cleanups_to_remove {
114-
let cleanup = match &mut body.basic_blocks_mut()[id].terminator {
115-
Some(Terminator { kind: TerminatorKind::Call { cleanup, .. }, .. }) => cleanup,
116-
_ => unreachable!(),
117-
};
134+
let cleanup = get_cleanup(body.basic_blocks_mut()[id].terminator_mut());
118135
*cleanup = None;
119136
}
120137

121138
// We may have invalidated some `cleanup` blocks so clean those up now.
122139
super::simplify::remove_dead_blocks(tcx, body);
123140
}
124141
}
142+
143+
fn get_cleanup<'a>(t: &'a mut Terminator<'_>) -> &'a mut Option<BasicBlock> {
144+
match &mut t.kind {
145+
TerminatorKind::Call { cleanup, .. }
146+
| TerminatorKind::Drop { unwind: cleanup, .. }
147+
| TerminatorKind::DropAndReplace { unwind: cleanup, .. }
148+
| TerminatorKind::Assert { cleanup, .. }
149+
| TerminatorKind::FalseUnwind { unwind: cleanup, .. } => cleanup,
150+
_ => unreachable!(),
151+
}
152+
}

compiler/rustc_mir/src/transform/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,10 @@ fn run_post_borrowck_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tc
458458
// These next passes must be executed together
459459
&add_call_guards::CriticalCallEdges,
460460
&elaborate_drops::ElaborateDrops,
461+
// This will remove extraneous landing pads which are no longer
462+
// necessary as well as well as forcing any call in a non-unwinding
463+
// function calling a possibly-unwinding function to abort the process.
464+
&abort_unwinding_calls::AbortUnwindingCalls,
461465
// AddMovesForPackedDrops needs to run after drop
462466
// elaboration.
463467
&add_moves_for_packed_drops::AddMovesForPackedDrops,
@@ -528,10 +532,6 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
528532

529533
// Some cleanup necessary at least for LLVM and potentially other codegen backends.
530534
let pre_codegen_cleanup: &[&dyn MirPass<'tcx>] = &[
531-
// This will remove extraneous landing pads which are no longer
532-
// necessary as well as well as forcing any call in a non-unwinding
533-
// function calling a possibly-unwinding function to abort the process.
534-
&abort_unwinding_calls::AbortUnwindingCalls,
535535
&add_call_guards::CriticalCallEdges,
536536
// Dump the end result for testing and debugging purposes.
537537
&dump_mir::Marker("PreCodegen"),

0 commit comments

Comments
 (0)