Skip to content

Commit 899d89f

Browse files
committed
coverage: Use a standard depth-first search on a custom subgraph
1 parent 8834b5a commit 899d89f

1 file changed

Lines changed: 31 additions & 29 deletions

File tree

  • compiler/rustc_mir_transform/src/coverage

‎compiler/rustc_mir_transform/src/coverage/graph.rs‎

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -145,18 +145,17 @@ impl CoverageGraph {
145145
bcbs.push(bcb_data);
146146
};
147147

148-
// Walk the MIR CFG using a Preorder traversal, which starts from `START_BLOCK` and follows
149-
// each block terminator's `successors()`. Coverage spans must map to actual source code,
150-
// so compiler generated blocks and paths can be ignored. To that end, the CFG traversal
151-
// intentionally omits unwind paths.
152-
// FIXME(#78544): MIR InstrumentCoverage: Improve coverage of `#[should_panic]` tests and
153-
// `catch_unwind()` handlers.
148+
// Traverse the MIR control-flow graph, accumulating chains of blocks
149+
// that can be combined into a single node in the coverage graph.
150+
// A depth-first search ensures that if two nodes can be chained
151+
// together, they will be adjacent in the traversal order.
154152

155153
// Accumulates a chain of blocks that will be combined into one BCB.
156154
letmut basic_blocks = Vec::new();
157155

158156
let filtered_successors = |bb| bcb_filtered_successors(mir_body[bb].terminator());
159-
for bb inshort_circuit_preorder(mir_body, filtered_successors)
157+
let subgraph = CoverageRelevantSubgraph::new(&mir_body.basic_blocks);
158+
for bb in graph::depth_first_search(subgraph, mir::START_BLOCK)
160159
.filter(|&bb| mir_body[bb].terminator().kind != TerminatorKind::Unreachable)
161160
{
162161
// If the previous block can't be chained into `bb`, flush the accumulated
@@ -599,28 +598,31 @@ impl<'a> TraverseCoverageGraphWithLoops<'a> {
599598
}
600599
}
601600

602-
fnshort_circuit_preorder<'a,'tcx,F,Iter>(
603-
body:&'a mir::Body<'tcx>,
604-
filtered_successors:F,
605-
) -> implIterator<Item = BasicBlock> + Captures<'a> + Captures<'tcx>
606-
where
607-
F:Fn(BasicBlock) -> Iter,
608-
Iter:IntoIterator<Item = BasicBlock>,
609-
{
610-
letmut visited = BitSet::new_empty(body.basic_blocks.len());
611-
letmut worklist = vec![mir::START_BLOCK];
612-
613-
std::iter::from_fn(move || {
614-
whileletSome(bb) = worklist.pop(){
615-
if !visited.insert(bb){
616-
continue;
617-
}
618-
619-
worklist.extend(filtered_successors(bb));
601+
/// Wrapper around a [`mir::BasicBlocks`] graph that restricts each node's
602+
/// successors to only the ones considered "relevant" when building a coverage
603+
/// graph.
604+
#[derive(Clone,Copy)]
605+
structCoverageRelevantSubgraph<'a,'tcx>{
606+
basic_blocks:&'a mir::BasicBlocks<'tcx>,
607+
}
608+
impl<'a,'tcx>CoverageRelevantSubgraph<'a,'tcx>{
609+
fnnew(basic_blocks:&'a mir::BasicBlocks<'tcx>) -> Self{
610+
Self{ basic_blocks }
611+
}
620612

621-
returnSome(bb);
622-
}
613+
fncoverage_successors(&self,bb:BasicBlock) -> CoverageSuccessors<'_>{
614+
bcb_filtered_successors(self.basic_blocks[bb].terminator())
615+
}
616+
}
617+
impl<'a,'tcx> graph::DirectedGraphforCoverageRelevantSubgraph<'a,'tcx>{
618+
typeNode = BasicBlock;
623619

624-
None
625-
})
620+
fnnum_nodes(&self) -> usize{
621+
self.basic_blocks.num_nodes()
622+
}
623+
}
624+
impl<'a,'tcx> graph::SuccessorsforCoverageRelevantSubgraph<'a,'tcx>{
625+
fnsuccessors(&self,bb:Self::Node) -> implIterator<Item = Self::Node>{
626+
self.coverage_successors(bb).into_iter()
627+
}
626628
}

0 commit comments

Comments
 (0)