Skip to content

Commit 899d89f

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

File tree

1 file changed

+31
-29
lines changed
  • compiler/rustc_mir_transform/src/coverage

1 file changed

+31
-29
lines changed

compiler/rustc_mir_transform/src/coverage/graph.rs

+31-29
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
let mut basic_blocks = Vec::new();
157155

158156
let filtered_successors = |bb| bcb_filtered_successors(mir_body[bb].terminator());
159-
for bb in short_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-
fn short_circuit_preorder<'a, 'tcx, F, Iter>(
603-
body: &'a mir::Body<'tcx>,
604-
filtered_successors: F,
605-
) -> impl Iterator<Item = BasicBlock> + Captures<'a> + Captures<'tcx>
606-
where
607-
F: Fn(BasicBlock) -> Iter,
608-
Iter: IntoIterator<Item = BasicBlock>,
609-
{
610-
let mut visited = BitSet::new_empty(body.basic_blocks.len());
611-
let mut worklist = vec![mir::START_BLOCK];
612-
613-
std::iter::from_fn(move || {
614-
while let Some(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+
struct CoverageRelevantSubgraph<'a, 'tcx> {
606+
basic_blocks: &'a mir::BasicBlocks<'tcx>,
607+
}
608+
impl<'a, 'tcx> CoverageRelevantSubgraph<'a, 'tcx> {
609+
fn new(basic_blocks: &'a mir::BasicBlocks<'tcx>) -> Self {
610+
Self { basic_blocks }
611+
}
620612

621-
return Some(bb);
622-
}
613+
fn coverage_successors(&self, bb: BasicBlock) -> CoverageSuccessors<'_> {
614+
bcb_filtered_successors(self.basic_blocks[bb].terminator())
615+
}
616+
}
617+
impl<'a, 'tcx> graph::DirectedGraph for CoverageRelevantSubgraph<'a, 'tcx> {
618+
type Node = BasicBlock;
623619

624-
None
625-
})
620+
fn num_nodes(&self) -> usize {
621+
self.basic_blocks.num_nodes()
622+
}
623+
}
624+
impl<'a, 'tcx> graph::Successors for CoverageRelevantSubgraph<'a, 'tcx> {
625+
fn successors(&self, bb: Self::Node) -> impl Iterator<Item = Self::Node> {
626+
self.coverage_successors(bb).into_iter()
627+
}
626628
}

0 commit comments

Comments
 (0)