@@ -14,16 +14,16 @@ use std::ops::{Index, IndexMut};
14
14
/// A coverage-specific simplification of the MIR control flow graph (CFG). The `CoverageGraph`s
15
15
/// nodes are `BasicCoverageBlock`s, which encompass one or more MIR `BasicBlock`s.
16
16
#[derive(Debug)]
17
- pub(super ) struct CoverageGraph {
17
+ pub(crate ) struct CoverageGraph {
18
18
bcbs: IndexVec<BasicCoverageBlock, BasicCoverageBlockData>,
19
19
bb_to_bcb: IndexVec<BasicBlock, Option<BasicCoverageBlock>>,
20
- pub successors: IndexVec<BasicCoverageBlock, Vec<BasicCoverageBlock>>,
21
- pub predecessors: IndexVec<BasicCoverageBlock, Vec<BasicCoverageBlock>>,
20
+ pub(crate) successors: IndexVec<BasicCoverageBlock, Vec<BasicCoverageBlock>>,
21
+ pub(crate) predecessors: IndexVec<BasicCoverageBlock, Vec<BasicCoverageBlock>>,
22
22
dominators: Option<Dominators<BasicCoverageBlock>>,
23
23
}
24
24
25
25
impl CoverageGraph {
26
- pub fn from_mir(mir_body: &mir::Body<'_>) -> Self {
26
+ pub(crate) fn from_mir(mir_body: &mir::Body<'_>) -> Self {
27
27
let (bcbs, bb_to_bcb) = Self::compute_basic_coverage_blocks(mir_body);
28
28
29
29
// Pre-transform MIR `BasicBlock` successors and predecessors into the BasicCoverageBlock
@@ -135,24 +135,28 @@ impl CoverageGraph {
135
135
}
136
136
137
137
#[inline(always)]
138
- pub fn iter_enumerated(
138
+ pub(crate) fn iter_enumerated(
139
139
&self,
140
140
) -> impl Iterator<Item = (BasicCoverageBlock, &BasicCoverageBlockData)> {
141
141
self.bcbs.iter_enumerated()
142
142
}
143
143
144
144
#[inline(always)]
145
- pub fn bcb_from_bb(&self, bb: BasicBlock) -> Option<BasicCoverageBlock> {
145
+ pub(crate) fn bcb_from_bb(&self, bb: BasicBlock) -> Option<BasicCoverageBlock> {
146
146
if bb.index() < self.bb_to_bcb.len() { self.bb_to_bcb[bb] } else { None }
147
147
}
148
148
149
149
#[inline(always)]
150
- pub fn dominates(&self, dom: BasicCoverageBlock, node: BasicCoverageBlock) -> bool {
150
+ pub(crate) fn dominates(&self, dom: BasicCoverageBlock, node: BasicCoverageBlock) -> bool {
151
151
self.dominators.as_ref().unwrap().dominates(dom, node)
152
152
}
153
153
154
154
#[inline(always)]
155
- pub fn cmp_in_dominator_order(&self, a: BasicCoverageBlock, b: BasicCoverageBlock) -> Ordering {
155
+ pub(crate) fn cmp_in_dominator_order(
156
+ &self,
157
+ a: BasicCoverageBlock,
158
+ b: BasicCoverageBlock,
159
+ ) -> Ordering {
156
160
self.dominators.as_ref().unwrap().cmp_in_dominator_order(a, b)
157
161
}
158
162
@@ -166,7 +170,7 @@ impl CoverageGraph {
166
170
///
167
171
/// FIXME: That assumption might not be true for [`TerminatorKind::Yield`]?
168
172
#[inline(always)]
169
- pub(super ) fn bcb_has_multiple_in_edges(&self, bcb: BasicCoverageBlock) -> bool {
173
+ pub(crate ) fn bcb_has_multiple_in_edges(&self, bcb: BasicCoverageBlock) -> bool {
170
174
// Even though bcb0 conceptually has an extra virtual in-edge due to
171
175
// being the entry point, we've already asserted that it has no _other_
172
176
// in-edges, so there's no possibility of it having _multiple_ in-edges.
@@ -212,7 +216,7 @@ impl graph::StartNode for CoverageGraph {
212
216
impl graph::Successors for CoverageGraph {
213
217
#[inline]
214
218
fn successors(&self, node: Self::Node) -> impl Iterator<Item = Self::Node> {
215
- self.successors[node].iter().cloned ()
219
+ self.successors[node].iter().copied ()
216
220
}
217
221
}
218
222
@@ -227,7 +231,7 @@ rustc_index::newtype_index! {
227
231
/// A node in the control-flow graph of CoverageGraph.
228
232
#[orderable]
229
233
#[debug_format = "bcb{}"]
230
- pub(super ) struct BasicCoverageBlock {
234
+ pub(crate ) struct BasicCoverageBlock {
231
235
const START_BCB = 0;
232
236
}
233
237
}
@@ -259,23 +263,23 @@ rustc_index::newtype_index! {
259
263
/// queries (`dominates()`, `predecessors`, `successors`, etc.) have branch (control flow)
260
264
/// significance.
261
265
#[derive(Debug, Clone)]
262
- pub(super ) struct BasicCoverageBlockData {
263
- pub basic_blocks: Vec<BasicBlock>,
266
+ pub(crate ) struct BasicCoverageBlockData {
267
+ pub(crate) basic_blocks: Vec<BasicBlock>,
264
268
}
265
269
266
270
impl BasicCoverageBlockData {
267
- pub fn from(basic_blocks: Vec<BasicBlock>) -> Self {
271
+ fn from(basic_blocks: Vec<BasicBlock>) -> Self {
268
272
assert!(basic_blocks.len() > 0);
269
273
Self { basic_blocks }
270
274
}
271
275
272
276
#[inline(always)]
273
- pub fn leader_bb(&self) -> BasicBlock {
277
+ pub(crate) fn leader_bb(&self) -> BasicBlock {
274
278
self.basic_blocks[0]
275
279
}
276
280
277
281
#[inline(always)]
278
- pub fn last_bb(&self) -> BasicBlock {
282
+ pub(crate) fn last_bb(&self) -> BasicBlock {
279
283
*self.basic_blocks.last().unwrap()
280
284
}
281
285
}
@@ -364,7 +368,7 @@ fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> Covera
364
368
/// CoverageGraph outside all loops. This supports traversing the BCB CFG in a way that
365
369
/// ensures a loop is completely traversed before processing Blocks after the end of the loop.
366
370
#[derive(Debug)]
367
- pub(super) struct TraversalContext {
371
+ struct TraversalContext {
368
372
/// BCB with one or more incoming loop backedges, indicating which loop
369
373
/// this context is for.
370
374
///
@@ -375,7 +379,7 @@ pub(super) struct TraversalContext {
375
379
worklist: VecDeque<BasicCoverageBlock>,
376
380
}
377
381
378
- pub(super ) struct TraverseCoverageGraphWithLoops<'a> {
382
+ pub(crate ) struct TraverseCoverageGraphWithLoops<'a> {
379
383
basic_coverage_blocks: &'a CoverageGraph,
380
384
381
385
backedges: IndexVec<BasicCoverageBlock, Vec<BasicCoverageBlock>>,
@@ -384,7 +388,7 @@ pub(super) struct TraverseCoverageGraphWithLoops<'a> {
384
388
}
385
389
386
390
impl<'a> TraverseCoverageGraphWithLoops<'a> {
387
- pub(super ) fn new(basic_coverage_blocks: &'a CoverageGraph) -> Self {
391
+ pub(crate ) fn new(basic_coverage_blocks: &'a CoverageGraph) -> Self {
388
392
let backedges = find_loop_backedges(basic_coverage_blocks);
389
393
390
394
let worklist = VecDeque::from([basic_coverage_blocks.start_node()]);
@@ -400,47 +404,46 @@ impl<'a> TraverseCoverageGraphWithLoops<'a> {
400
404
401
405
/// For each loop on the loop context stack (top-down), yields a list of BCBs
402
406
/// within that loop that have an outgoing edge back to the loop header.
403
- pub(super ) fn reloop_bcbs_per_loop(&self) -> impl Iterator<Item = &[BasicCoverageBlock]> {
407
+ pub(crate ) fn reloop_bcbs_per_loop(&self) -> impl Iterator<Item = &[BasicCoverageBlock]> {
404
408
self.context_stack
405
409
.iter()
406
410
.rev()
407
411
.filter_map(|context| context.loop_header)
408
412
.map(|header_bcb| self.backedges[header_bcb].as_slice())
409
413
}
410
414
411
- pub(super ) fn next(&mut self) -> Option<BasicCoverageBlock> {
415
+ pub(crate ) fn next(&mut self) -> Option<BasicCoverageBlock> {
412
416
debug!(
413
417
"TraverseCoverageGraphWithLoops::next - context_stack: {:?}",
414
418
self.context_stack.iter().rev().collect::<Vec<_>>()
415
419
);
416
420
417
421
while let Some(context) = self.context_stack.last_mut() {
418
- if let Some(bcb) = context.worklist.pop_front() {
419
- if !self.visited.insert(bcb) {
420
- debug!("Already visited: {bcb:?}");
421
- continue;
422
- }
423
- debug!("Visiting {bcb:?}");
424
-
425
- if self.backedges[bcb].len() > 0 {
426
- debug!("{bcb:?} is a loop header! Start a new TraversalContext...");
427
- self.context_stack.push(TraversalContext {
428
- loop_header: Some(bcb),
429
- worklist: VecDeque::new(),
430
- });
431
- }
432
- self.add_successors_to_worklists(bcb);
433
- return Some(bcb);
434
- } else {
435
- // Strip contexts with empty worklists from the top of the stack
422
+ let Some(bcb) = context.worklist.pop_front() else {
423
+ // This stack level is exhausted; pop it and try the next one.
436
424
self.context_stack.pop();
425
+ continue;
426
+ };
427
+
428
+ if !self.visited.insert(bcb) {
429
+ debug!("Already visited: {bcb:?}");
430
+ continue;
431
+ }
432
+ debug!("Visiting {bcb:?}");
433
+
434
+ if self.backedges[bcb].len() > 0 {
435
+ debug!("{bcb:?} is a loop header! Start a new TraversalContext...");
436
+ self.context_stack
437
+ .push(TraversalContext { loop_header: Some(bcb), worklist: VecDeque::new() });
437
438
}
439
+ self.add_successors_to_worklists(bcb);
440
+ return Some(bcb);
438
441
}
439
442
440
443
None
441
444
}
442
445
443
- pub fn add_successors_to_worklists(&mut self, bcb: BasicCoverageBlock) {
446
+ fn add_successors_to_worklists(&mut self, bcb: BasicCoverageBlock) {
444
447
let successors = &self.basic_coverage_blocks.successors[bcb];
445
448
debug!("{:?} has {} successors:", bcb, successors.len());
446
449
@@ -494,19 +497,19 @@ impl<'a> TraverseCoverageGraphWithLoops<'a> {
494
497
}
495
498
}
496
499
497
- pub fn is_complete(&self) -> bool {
500
+ pub(crate) fn is_complete(&self) -> bool {
498
501
self.visited.count() == self.visited.domain_size()
499
502
}
500
503
501
- pub fn unvisited(&self) -> Vec<BasicCoverageBlock> {
504
+ pub(crate) fn unvisited(&self) -> Vec<BasicCoverageBlock> {
502
505
let mut unvisited_set: BitSet<BasicCoverageBlock> =
503
506
BitSet::new_filled(self.visited.domain_size());
504
507
unvisited_set.subtract(&self.visited);
505
508
unvisited_set.iter().collect::<Vec<_>>()
506
509
}
507
510
}
508
511
509
- pub(super) fn find_loop_backedges(
512
+ fn find_loop_backedges(
510
513
basic_coverage_blocks: &CoverageGraph,
511
514
) -> IndexVec<BasicCoverageBlock, Vec<BasicCoverageBlock>> {
512
515
let num_bcbs = basic_coverage_blocks.num_nodes();
0 commit comments