Avoid trivial checks on cleanup control flow in MIR validator
This commit is contained in:
parent
ec3d993410
commit
4bc963eba6
1 changed files with 11 additions and 4 deletions
|
@ -64,6 +64,7 @@ impl<'tcx> MirPass<'tcx> for Validator {
|
||||||
tcx,
|
tcx,
|
||||||
param_env,
|
param_env,
|
||||||
mir_phase,
|
mir_phase,
|
||||||
|
unwind_edge_count: 0,
|
||||||
reachable_blocks: traversal::reachable_as_bitset(body),
|
reachable_blocks: traversal::reachable_as_bitset(body),
|
||||||
storage_liveness,
|
storage_liveness,
|
||||||
place_cache: Vec::new(),
|
place_cache: Vec::new(),
|
||||||
|
@ -80,6 +81,7 @@ struct TypeChecker<'a, 'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ParamEnv<'tcx>,
|
param_env: ParamEnv<'tcx>,
|
||||||
mir_phase: MirPhase,
|
mir_phase: MirPhase,
|
||||||
|
unwind_edge_count: usize,
|
||||||
reachable_blocks: BitSet<BasicBlock>,
|
reachable_blocks: BitSet<BasicBlock>,
|
||||||
storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive<'static>>,
|
storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive<'static>>,
|
||||||
place_cache: Vec<PlaceRef<'tcx>>,
|
place_cache: Vec<PlaceRef<'tcx>>,
|
||||||
|
@ -104,7 +106,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_edge(&self, location: Location, bb: BasicBlock, edge_kind: EdgeKind) {
|
fn check_edge(&mut self, location: Location, bb: BasicBlock, edge_kind: EdgeKind) {
|
||||||
if bb == START_BLOCK {
|
if bb == START_BLOCK {
|
||||||
self.fail(location, "start block must not have predecessors")
|
self.fail(location, "start block must not have predecessors")
|
||||||
}
|
}
|
||||||
|
@ -113,10 +115,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
match (src.is_cleanup, bb.is_cleanup, edge_kind) {
|
match (src.is_cleanup, bb.is_cleanup, edge_kind) {
|
||||||
// Non-cleanup blocks can jump to non-cleanup blocks along non-unwind edges
|
// Non-cleanup blocks can jump to non-cleanup blocks along non-unwind edges
|
||||||
(false, false, EdgeKind::Normal)
|
(false, false, EdgeKind::Normal)
|
||||||
// Non-cleanup blocks can jump to cleanup blocks along unwind edges
|
|
||||||
| (false, true, EdgeKind::Unwind)
|
|
||||||
// Cleanup blocks can jump to cleanup blocks along non-unwind edges
|
// Cleanup blocks can jump to cleanup blocks along non-unwind edges
|
||||||
| (true, true, EdgeKind::Normal) => {}
|
| (true, true, EdgeKind::Normal) => {}
|
||||||
|
// Non-cleanup blocks can jump to cleanup blocks along unwind edges
|
||||||
|
(false, true, EdgeKind::Unwind) => {
|
||||||
|
self.unwind_edge_count += 1;
|
||||||
|
}
|
||||||
// All other jumps are invalid
|
// All other jumps are invalid
|
||||||
_ => {
|
_ => {
|
||||||
self.fail(
|
self.fail(
|
||||||
|
@ -137,6 +141,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_cleanup_control_flow(&self) {
|
fn check_cleanup_control_flow(&self) {
|
||||||
|
if self.unwind_edge_count <= 1 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let doms = self.body.basic_blocks.dominators();
|
let doms = self.body.basic_blocks.dominators();
|
||||||
let mut post_contract_node = FxHashMap::default();
|
let mut post_contract_node = FxHashMap::default();
|
||||||
// Reusing the allocation across invocations of the closure
|
// Reusing the allocation across invocations of the closure
|
||||||
|
@ -196,7 +203,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
stack.clear();
|
stack.clear();
|
||||||
stack.insert(bb);
|
stack.insert(bb);
|
||||||
loop {
|
loop {
|
||||||
let Some(parent )= parent[bb].take() else {
|
let Some(parent)= parent[bb].take() else {
|
||||||
break
|
break
|
||||||
};
|
};
|
||||||
let no_cycle = stack.insert(parent);
|
let no_cycle = stack.insert(parent);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue