Add UnwindAction::Terminate
This commit is contained in:
parent
5e6ed132fa
commit
0a5dac3062
16 changed files with 126 additions and 121 deletions
|
@ -34,11 +34,6 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
|
|||
return;
|
||||
}
|
||||
|
||||
// This pass only runs on functions which themselves cannot unwind,
|
||||
// forcibly changing the body of the function to structurally provide
|
||||
// this guarantee by aborting on an unwind. If this function can unwind,
|
||||
// then there's nothing to do because it already should work correctly.
|
||||
//
|
||||
// Here we test for this function itself whether its ABI allows
|
||||
// unwinding or not.
|
||||
let body_ty = tcx.type_of(def_id).skip_binder();
|
||||
|
@ -107,26 +102,9 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
|
|||
}
|
||||
}
|
||||
|
||||
// For call instructions which need to be terminated, we insert a
|
||||
// singular basic block which simply terminates, and then configure the
|
||||
// `cleanup` attribute for all calls we found to this basic block we
|
||||
// insert which means that any unwinding that happens in the functions
|
||||
// will force an abort of the process.
|
||||
if !calls_to_terminate.is_empty() {
|
||||
let bb = BasicBlockData {
|
||||
statements: Vec::new(),
|
||||
is_cleanup: true,
|
||||
terminator: Some(Terminator {
|
||||
source_info: SourceInfo::outermost(body.span),
|
||||
kind: TerminatorKind::Abort,
|
||||
}),
|
||||
};
|
||||
let abort_bb = body.basic_blocks_mut().push(bb);
|
||||
|
||||
for bb in calls_to_terminate {
|
||||
let cleanup = body.basic_blocks_mut()[bb].terminator_mut().unwind_mut().unwrap();
|
||||
*cleanup = UnwindAction::Cleanup(abort_bb);
|
||||
}
|
||||
for id in calls_to_terminate {
|
||||
let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap();
|
||||
*cleanup = UnwindAction::Terminate;
|
||||
}
|
||||
|
||||
for id in cleanups_to_remove {
|
||||
|
|
|
@ -417,7 +417,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
|||
UnwindAction::Unreachable => {
|
||||
Unwind::To(self.patch.unreachable_block())
|
||||
}
|
||||
UnwindAction::Terminate => Unwind::To(self.patch.terminate_block()),
|
||||
UnwindAction::Terminate => {
|
||||
Unwind::To(self.patch.terminate_block())
|
||||
}
|
||||
}
|
||||
};
|
||||
elaborate_drop(
|
||||
|
@ -558,7 +560,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
|||
if let TerminatorKind::Call {
|
||||
destination,
|
||||
target: Some(_),
|
||||
unwind: UnwindAction::Continue,
|
||||
unwind: UnwindAction::Continue | UnwindAction::Unreachable | UnwindAction::Terminate,
|
||||
..
|
||||
} = data.terminator().kind
|
||||
{
|
||||
|
|
|
@ -1064,6 +1064,7 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
|||
UnwindAction::Cleanup(tgt) => tgt,
|
||||
UnwindAction::Continue => elaborator.patch.resume_block(),
|
||||
UnwindAction::Unreachable => elaborator.patch.unreachable_block(),
|
||||
UnwindAction::Terminate => elaborator.patch.terminate_block(),
|
||||
})
|
||||
};
|
||||
elaborate_drop(
|
||||
|
|
|
@ -1017,15 +1017,15 @@ impl Integrator<'_, '_> {
|
|||
fn map_unwind(&self, unwind: UnwindAction) -> UnwindAction {
|
||||
if self.in_cleanup_block {
|
||||
match unwind {
|
||||
UnwindAction::Cleanup(_) => {
|
||||
UnwindAction::Cleanup(_) | UnwindAction::Continue => {
|
||||
bug!("cleanup on cleanup block");
|
||||
}
|
||||
UnwindAction::Continue | UnwindAction::Unreachable => return unwind,
|
||||
UnwindAction::Unreachable | UnwindAction::Terminate => return unwind,
|
||||
}
|
||||
}
|
||||
|
||||
match unwind {
|
||||
UnwindAction::Unreachable => unwind,
|
||||
UnwindAction::Unreachable | UnwindAction::Terminate => unwind,
|
||||
UnwindAction::Cleanup(target) => UnwindAction::Cleanup(self.map_block(target)),
|
||||
// Add an unwind edge to the original call's cleanup block
|
||||
UnwindAction::Continue => self.cleanup_block,
|
||||
|
@ -1141,7 +1141,10 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
|
|||
terminator.kind = TerminatorKind::Goto { target: tgt };
|
||||
}
|
||||
UnwindAction::Continue => (),
|
||||
UnwindAction::Unreachable => {
|
||||
UnwindAction::Unreachable | UnwindAction::Terminate => {
|
||||
// If the action is terminate, then we would have mapped marked
|
||||
// all our call-sites as `UnwindAction::Terminate` and no cleanup
|
||||
// blocks would ever be executed.
|
||||
terminator.kind = TerminatorKind::Unreachable;
|
||||
}
|
||||
},
|
||||
|
|
|
@ -54,7 +54,6 @@ fn lower_slice_len_call<'tcx>(
|
|||
args,
|
||||
destination,
|
||||
target: Some(bb),
|
||||
unwind: UnwindAction::Unreachable,
|
||||
from_hir_call: true,
|
||||
..
|
||||
} => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue