1
Fork 0

Refactor unwind from Option to a new enum

This commit is contained in:
Gary Guo 2022-10-08 23:47:59 +01:00
parent 7f6edd3f15
commit daeb844e0c
39 changed files with 328 additions and 250 deletions

View file

@ -125,13 +125,13 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
for bb in calls_to_terminate {
let cleanup = body.basic_blocks_mut()[bb].terminator_mut().unwind_mut().unwrap();
*cleanup = Some(abort_bb);
*cleanup = UnwindAction::Cleanup(abort_bb);
}
}
for id in cleanups_to_remove {
let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap();
*cleanup = None;
*cleanup = UnwindAction::Continue;
}
// We may have invalidated some `cleanup` blocks so clean those up now.

View file

@ -50,10 +50,10 @@ impl AddCallGuards {
for block in body.basic_blocks_mut() {
match block.terminator {
Some(Terminator {
kind: TerminatorKind::Call { target: Some(ref mut destination), cleanup, .. },
kind: TerminatorKind::Call { target: Some(ref mut destination), unwind, .. },
source_info,
}) if pred_count[*destination] > 1
&& (cleanup.is_some() || self == &AllCallEdges) =>
&& (matches!(unwind, UnwindAction::Cleanup(_)) || self == &AllCallEdges) =>
{
// It's a critical edge, break it
let call_guard = BasicBlockData {

View file

@ -228,7 +228,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
fn assert_panic(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
_msg: &rustc_middle::mir::AssertMessage<'tcx>,
_unwind: Option<rustc_middle::mir::BasicBlock>,
_unwind: rustc_middle::mir::UnwindAction,
) -> InterpResult<'tcx> {
bug!("panics terminators are not evaluated in ConstProp")
}

View file

@ -140,7 +140,7 @@ impl<'tcx> MockBlocks<'tcx> {
args: vec![],
destination: self.dummy_place.clone(),
target: Some(TEMP_BLOCK),
cleanup: None,
unwind: UnwindAction::Continue,
from_hir_call: false,
fn_span: DUMMY_SP,
},

View file

@ -120,7 +120,7 @@ fn remove_dead_unwinds<'tcx>(
.into_results_cursor(body);
for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
let place = match bb_data.terminator().kind {
TerminatorKind::Drop { ref place, unwind: Some(_), .. } => {
TerminatorKind::Drop { ref place, unwind: UnwindAction::Cleanup(_), .. } => {
und.derefer(place.as_ref(), body).unwrap_or(*place)
}
_ => continue,
@ -417,7 +417,10 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
if data.is_cleanup {
Unwind::InCleanup
} else {
Unwind::To(Option::unwrap_or(unwind, resume_block))
match unwind {
UnwindAction::Cleanup(cleanup) => Unwind::To(cleanup),
UnwindAction::Continue => Unwind::To(resume_block),
}
},
bb,
),
@ -474,7 +477,10 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
continue;
}
if let TerminatorKind::Call {
destination, target: Some(tgt), cleanup: Some(_), ..
destination,
target: Some(tgt),
unwind: UnwindAction::Cleanup(_),
..
} = data.terminator().kind
{
assert!(!self.patch.is_patched(bb));
@ -543,8 +549,12 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
// There may be a critical edge after this call,
// so mark the return as initialized *before* the
// call.
if let TerminatorKind::Call { destination, target: Some(_), cleanup: None, .. } =
data.terminator().kind
if let TerminatorKind::Call {
destination,
target: Some(_),
unwind: UnwindAction::Continue,
..
} = data.terminator().kind
{
assert!(!self.patch.is_patched(bb));

View file

@ -34,7 +34,7 @@ impl<'tcx> Visitor<'tcx> for FunctionItemRefChecker<'_, 'tcx> {
args,
destination: _,
target: _,
cleanup: _,
unwind: _,
from_hir_call: _,
fn_span: _,
} = &terminator.kind

View file

@ -1060,7 +1060,10 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let unwind = if block_data.is_cleanup {
Unwind::InCleanup
} else {
Unwind::To(unwind.unwrap_or_else(|| elaborator.patch.resume_block()))
Unwind::To(match *unwind {
UnwindAction::Cleanup(tgt) => tgt,
UnwindAction::Continue => elaborator.patch.resume_block(),
})
};
elaborate_drop(
&mut elaborator,
@ -1147,7 +1150,7 @@ fn insert_panic_block<'tcx>(
expected: true,
msg: message,
target: assert_block,
cleanup: None,
unwind: UnwindAction::Continue,
};
let source_info = SourceInfo::outermost(body.span);
@ -1248,8 +1251,8 @@ fn create_generator_resume_function<'tcx>(
} else if !block.is_cleanup {
// Any terminators that *can* unwind but don't have an unwind target set are also
// pointed at our poisoning block (unless they're part of the cleanup path).
if let Some(unwind @ None) = block.terminator_mut().unwind_mut() {
*unwind = Some(poison_block);
if let Some(unwind @ UnwindAction::Continue) = block.terminator_mut().unwind_mut() {
*unwind = UnwindAction::Cleanup(poison_block);
}
}
}
@ -1294,8 +1297,11 @@ fn create_generator_resume_function<'tcx>(
fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock {
let return_block = insert_term_block(body, TerminatorKind::Return);
let term =
TerminatorKind::Drop { place: Place::from(SELF_ARG), target: return_block, unwind: None };
let term = TerminatorKind::Drop {
place: Place::from(SELF_ARG),
target: return_block,
unwind: UnwindAction::Continue,
};
let source_info = SourceInfo::outermost(body.span);
// Create a block to destroy an unresumed generators. This can only destroy upvars.
@ -1670,7 +1676,7 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
args,
destination,
target: Some(_),
cleanup: _,
unwind: _,
from_hir_call: _,
fn_span: _,
} => {

View file

@ -453,7 +453,7 @@ impl<'tcx> Inliner<'tcx> {
// If the place doesn't actually need dropping, treat it like a regular goto.
let ty = callsite.callee.subst_mir(self.tcx, &place.ty(callee_body, tcx).ty);
if ty.needs_drop(tcx, self.param_env) && let Some(unwind) = unwind {
if ty.needs_drop(tcx, self.param_env) && let UnwindAction::Cleanup(unwind) = unwind {
work_list.push(unwind);
}
} else if callee_attrs.instruction_set != self.codegen_fn_attrs.instruction_set
@ -500,7 +500,7 @@ impl<'tcx> Inliner<'tcx> {
) {
let terminator = caller_body[callsite.block].terminator.take().unwrap();
match terminator.kind {
TerminatorKind::Call { args, destination, cleanup, .. } => {
TerminatorKind::Call { args, destination, unwind, .. } => {
// If the call is something like `a[*i] = f(i)`, where
// `i : &mut usize`, then just duplicating the `a[*i]`
// Place could result in two different locations if `f`
@ -571,7 +571,7 @@ impl<'tcx> Inliner<'tcx> {
destination: destination_local,
callsite_scope: caller_body.source_scopes[callsite.source_info.scope].clone(),
callsite,
cleanup_block: cleanup,
cleanup_block: unwind,
in_cleanup_block: false,
tcx: self.tcx,
expn_data,
@ -813,14 +813,14 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
let ty = self.instance.subst_mir(tcx, &place.ty(self.callee_body, tcx).ty);
if ty.needs_drop(tcx, self.param_env) {
self.cost += CALL_PENALTY;
if unwind.is_some() {
if let UnwindAction::Cleanup(_) = unwind {
self.cost += LANDINGPAD_PENALTY;
}
} else {
self.cost += INSTR_COST;
}
}
TerminatorKind::Call { func: Operand::Constant(ref f), cleanup, .. } => {
TerminatorKind::Call { func: Operand::Constant(ref f), unwind, .. } => {
let fn_ty = self.instance.subst_mir(tcx, &f.literal.ty());
self.cost += if let ty::FnDef(def_id, _) = *fn_ty.kind() && tcx.is_intrinsic(def_id) {
// Don't give intrinsics the extra penalty for calls
@ -828,20 +828,20 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
} else {
CALL_PENALTY
};
if cleanup.is_some() {
if let UnwindAction::Cleanup(_) = unwind {
self.cost += LANDINGPAD_PENALTY;
}
}
TerminatorKind::Assert { cleanup, .. } => {
TerminatorKind::Assert { unwind, .. } => {
self.cost += CALL_PENALTY;
if cleanup.is_some() {
if let UnwindAction::Cleanup(_) = unwind {
self.cost += LANDINGPAD_PENALTY;
}
}
TerminatorKind::Resume => self.cost += RESUME_PENALTY,
TerminatorKind::InlineAsm { cleanup, .. } => {
TerminatorKind::InlineAsm { unwind, .. } => {
self.cost += INSTR_COST;
if cleanup.is_some() {
if let UnwindAction::Cleanup(_) = unwind {
self.cost += LANDINGPAD_PENALTY;
}
}
@ -979,7 +979,7 @@ struct Integrator<'a, 'tcx> {
destination: Local,
callsite_scope: SourceScopeData<'tcx>,
callsite: &'a CallSite<'tcx>,
cleanup_block: Option<BasicBlock>,
cleanup_block: UnwindAction,
in_cleanup_block: bool,
tcx: TyCtxt<'tcx>,
expn_data: LocalExpnId,
@ -1014,18 +1014,20 @@ impl Integrator<'_, '_> {
new
}
fn map_unwind(&self, unwind: Option<BasicBlock>) -> Option<BasicBlock> {
fn map_unwind(&self, unwind: UnwindAction) -> UnwindAction {
if self.in_cleanup_block {
if unwind.is_some() {
bug!("cleanup on cleanup block");
match unwind {
UnwindAction::Cleanup(_) => {
bug!("cleanup on cleanup block");
}
UnwindAction::Continue => return unwind,
}
return unwind;
}
match unwind {
Some(target) => Some(self.map_block(target)),
UnwindAction::Cleanup(target) => UnwindAction::Cleanup(self.map_block(target)),
// Add an unwind edge to the original call's cleanup block
None => self.cleanup_block,
UnwindAction::Continue => self.cleanup_block,
}
}
}
@ -1116,15 +1118,15 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
*target = self.map_block(*target);
*unwind = self.map_unwind(*unwind);
}
TerminatorKind::Call { ref mut target, ref mut cleanup, .. } => {
TerminatorKind::Call { ref mut target, ref mut unwind, .. } => {
if let Some(ref mut tgt) = *target {
*tgt = self.map_block(*tgt);
}
*cleanup = self.map_unwind(*cleanup);
*unwind = self.map_unwind(*unwind);
}
TerminatorKind::Assert { ref mut target, ref mut cleanup, .. } => {
TerminatorKind::Assert { ref mut target, ref mut unwind, .. } => {
*target = self.map_block(*target);
*cleanup = self.map_unwind(*cleanup);
*unwind = self.map_unwind(*unwind);
}
TerminatorKind::Return => {
terminator.kind = if let Some(tgt) = self.callsite.target {
@ -1133,11 +1135,12 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
TerminatorKind::Unreachable
}
}
TerminatorKind::Resume => {
if let Some(tgt) = self.cleanup_block {
terminator.kind = TerminatorKind::Goto { target: tgt }
TerminatorKind::Resume => match self.cleanup_block {
UnwindAction::Cleanup(tgt) => {
terminator.kind = TerminatorKind::Goto { target: tgt };
}
}
UnwindAction::Continue => (),
},
TerminatorKind::Abort => {}
TerminatorKind::Unreachable => {}
TerminatorKind::FalseEdge { ref mut real_target, ref mut imaginary_target } => {
@ -1149,11 +1152,11 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
{
bug!("False unwinds should have been removed before inlining")
}
TerminatorKind::InlineAsm { ref mut destination, ref mut cleanup, .. } => {
TerminatorKind::InlineAsm { ref mut destination, ref mut unwind, .. } => {
if let Some(ref mut tgt) = *destination {
*tgt = self.map_block(*tgt);
}
*cleanup = self.map_unwind(*cleanup);
*unwind = self.map_unwind(*unwind);
}
}
}

View file

@ -159,7 +159,7 @@ fn remap_mir_for_const_eval_select<'tcx>(
ref mut args,
destination,
target,
cleanup,
unwind,
fn_span,
..
} if let ty::FnDef(def_id, _) = *literal.ty().kind()
@ -196,7 +196,7 @@ fn remap_mir_for_const_eval_select<'tcx>(
};
method(place)
}).collect();
terminator.kind = TerminatorKind::Call { func, args: arguments, destination, target, cleanup, from_hir_call: false, fn_span };
terminator.kind = TerminatorKind::Call { func, args: arguments, destination, target, unwind, from_hir_call: false, fn_span };
}
_ => {}
}

View file

@ -54,7 +54,7 @@ fn lower_slice_len_call<'tcx>(
args,
destination,
target: Some(bb),
cleanup: None,
unwind: UnwindAction::Continue,
from_hir_call: true,
..
} => {

View file

@ -103,11 +103,11 @@ impl RemoveNoopLandingPads {
for bb in postorder {
debug!(" processing {:?}", bb);
if let Some(unwind) = body[bb].terminator_mut().unwind_mut() {
if let Some(unwind_bb) = *unwind {
if let UnwindAction::Cleanup(unwind_bb) = *unwind {
if nop_landing_pads.contains(unwind_bb) {
debug!(" removing noop landing pad");
landing_pads_removed += 1;
*unwind = None;
*unwind = UnwindAction::Continue;
}
}
}

View file

@ -499,7 +499,7 @@ impl<'tcx> CloneShimBuilder<'tcx> {
args: vec![Operand::Move(ref_loc)],
destination: dest,
target: Some(next),
cleanup: Some(cleanup),
unwind: UnwindAction::Cleanup(cleanup),
from_hir_call: true,
fn_span: self.span,
},
@ -540,7 +540,11 @@ impl<'tcx> CloneShimBuilder<'tcx> {
self.make_clone_call(dest_field, src_field, ity, next_block, unwind);
self.block(
vec![],
TerminatorKind::Drop { place: dest_field, target: unwind, unwind: None },
TerminatorKind::Drop {
place: dest_field,
target: unwind,
unwind: UnwindAction::Continue,
},
true,
);
unwind = next_unwind;
@ -776,10 +780,10 @@ fn build_call_shim<'tcx>(
args,
destination: Place::return_place(),
target: Some(BasicBlock::new(1)),
cleanup: if let Some(Adjustment::RefMut) = rcvr_adjustment {
Some(BasicBlock::new(3))
unwind: if let Some(Adjustment::RefMut) = rcvr_adjustment {
UnwindAction::Cleanup(BasicBlock::new(3))
} else {
None
UnwindAction::Continue
},
from_hir_call: true,
fn_span: span,
@ -792,7 +796,11 @@ fn build_call_shim<'tcx>(
block(
&mut blocks,
vec![],
TerminatorKind::Drop { place: rcvr_place(), target: BasicBlock::new(2), unwind: None },
TerminatorKind::Drop {
place: rcvr_place(),
target: BasicBlock::new(2),
unwind: UnwindAction::Continue,
},
false,
);
}
@ -803,7 +811,11 @@ fn build_call_shim<'tcx>(
block(
&mut blocks,
vec![],
TerminatorKind::Drop { place: rcvr_place(), target: BasicBlock::new(4), unwind: None },
TerminatorKind::Drop {
place: rcvr_place(),
target: BasicBlock::new(4),
unwind: UnwindAction::Continue,
},
true,
);