Skip to content

Commit b502064

Browse files
committed
Implemented CoverageGraph of BasicCoverageBlocks
1 parent c7ae4c2 commit b502064

File tree

61 files changed

+563
-493
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+563
-493
lines changed

compiler/rustc_mir/src/transform/coverage/debug.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::graph::BasicCoverageBlocks;
1+
use super::graph::CoverageGraph;
22
use super::spans::CoverageSpan;
33

44
use crate::util::pretty;
@@ -11,7 +11,7 @@ use rustc_middle::ty::TyCtxt;
1111
pub(crate) fn dump_coverage_spanview(
1212
tcx: TyCtxt<'tcx>,
1313
mir_body: &mir::Body<'tcx>,
14-
basic_coverage_blocks: &BasicCoverageBlocks,
14+
basic_coverage_blocks: &CoverageGraph,
1515
pass_name: &str,
1616
coverage_spans: &Vec<CoverageSpan>,
1717
) {
@@ -28,20 +28,20 @@ pub(crate) fn dump_coverage_spanview(
2828
.expect("Unexpected IO error dumping coverage spans as HTML");
2929
}
3030

31-
/// Converts the computed `BasicCoverageBlock`s into `SpanViewable`s.
31+
/// Converts the computed `BasicCoverageBlockData`s into `SpanViewable`s.
3232
fn span_viewables(
3333
tcx: TyCtxt<'tcx>,
3434
mir_body: &mir::Body<'tcx>,
35-
basic_coverage_blocks: &BasicCoverageBlocks,
35+
basic_coverage_blocks: &CoverageGraph,
3636
coverage_spans: &Vec<CoverageSpan>,
3737
) -> Vec<SpanViewable> {
3838
let mut span_viewables = Vec::new();
3939
for coverage_span in coverage_spans {
4040
let tooltip = coverage_span.format_coverage_statements(tcx, mir_body);
41-
let CoverageSpan { span, bcb_leader_bb: bb, .. } = coverage_span;
42-
let bcb = &basic_coverage_blocks[*bb];
43-
let id = bcb.id();
44-
let leader_bb = bcb.leader_bb();
41+
let CoverageSpan { span, bcb, .. } = coverage_span;
42+
let bcb_data = &basic_coverage_blocks[*bcb];
43+
let id = bcb_data.id();
44+
let leader_bb = bcb_data.leader_bb();
4545
span_viewables.push(SpanViewable { bb: leader_bb, span: *span, id, tooltip });
4646
}
4747
span_viewables

compiler/rustc_mir/src/transform/coverage/graph.rs

Lines changed: 301 additions & 157 deletions
Large diffs are not rendered by default.

compiler/rustc_mir/src/transform/coverage/mod.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ mod graph;
66
mod spans;
77

88
use counters::CoverageCounters;
9-
use graph::BasicCoverageBlocks;
9+
use graph::CoverageGraph;
1010
use spans::{CoverageSpan, CoverageSpans};
1111

1212
use crate::transform::MirPass;
1313
use crate::util::pretty;
1414

1515
use rustc_data_structures::fingerprint::Fingerprint;
16+
use rustc_data_structures::graph::WithNumNodes;
1617
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
1718
use rustc_data_structures::sync::Lrc;
1819
use rustc_index::vec::IndexVec;
@@ -73,7 +74,7 @@ struct Instrumentor<'a, 'tcx> {
7374
tcx: TyCtxt<'tcx>,
7475
mir_body: &'a mut mir::Body<'tcx>,
7576
body_span: Span,
76-
basic_coverage_blocks: BasicCoverageBlocks,
77+
basic_coverage_blocks: CoverageGraph,
7778
coverage_counters: CoverageCounters,
7879
}
7980

@@ -82,7 +83,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
8283
let hir_body = hir_body(tcx, mir_body.source.def_id());
8384
let body_span = hir_body.value.span;
8485
let function_source_hash = hash_mir_source(tcx, hir_body);
85-
let basic_coverage_blocks = BasicCoverageBlocks::from_mir(mir_body);
86+
let basic_coverage_blocks = CoverageGraph::from_mir(mir_body);
8687
Self {
8788
pass_name,
8889
tcx,
@@ -103,7 +104,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
103104
debug!("instrumenting {:?}, span: {}", def_id, source_map.span_to_string(body_span));
104105

105106
////////////////////////////////////////////////////
106-
// Compute `CoverageSpan`s from the `BasicCoverageBlocks`.
107+
// Compute `CoverageSpan`s from the `CoverageGraph`.
107108
let coverage_spans = CoverageSpans::generate_coverage_spans(
108109
&self.mir_body,
109110
body_span,
@@ -135,9 +136,11 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
135136
let source_file = source_map.lookup_source_file(body_span.lo());
136137
let file_name = Symbol::intern(&source_file.name.to_string());
137138

138-
let mut bb_counters = IndexVec::from_elem_n(None, self.mir_body.basic_blocks().len());
139-
for CoverageSpan { span, bcb_leader_bb: bb, .. } in coverage_spans {
140-
if let Some(&counter_operand) = bb_counters[bb].as_ref() {
139+
let mut bcb_counters = IndexVec::from_elem_n(None, self.basic_coverage_blocks.num_nodes());
140+
for covspan in coverage_spans {
141+
let bcb = covspan.bcb;
142+
let span = covspan.span;
143+
if let Some(&counter_operand) = bcb_counters[bcb].as_ref() {
141144
let expression = self.coverage_counters.make_expression(
142145
counter_operand,
143146
Op::Add,
@@ -149,6 +152,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
149152
span,
150153
source_map.span_to_snippet(span).expect("Error getting source for span"),
151154
);
155+
let bb = self.basic_coverage_blocks[bcb].leader_bb();
152156
let code_region = make_code_region(file_name, &source_file, span, body_span);
153157
inject_statement(self.mir_body, expression, bb, Some(code_region));
154158
} else {
@@ -160,7 +164,8 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
160164
source_map.span_to_snippet(span).expect("Error getting source for span"),
161165
);
162166
let counter_operand = counter.as_operand_id();
163-
bb_counters[bb] = Some(counter_operand);
167+
bcb_counters[bcb] = Some(counter_operand);
168+
let bb = self.basic_coverage_blocks[bcb].leader_bb();
164169
let code_region = make_code_region(file_name, &source_file, span, body_span);
165170
inject_statement(self.mir_body, counter, bb, Some(code_region));
166171
}

compiler/rustc_mir/src/transform/coverage/spans.rs

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
use super::debug::term_type;
2-
use super::graph::{BasicCoverageBlock, BasicCoverageBlocks};
2+
use super::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph};
33

44
use crate::util::spanview::source_range_no_file;
55

6-
use rustc_data_structures::graph::dominators::Dominators;
76
use rustc_data_structures::graph::WithNumNodes;
87
use rustc_index::bit_set::BitSet;
98
use rustc_middle::mir::{
@@ -69,7 +68,7 @@ impl CoverageStatement {
6968
#[derive(Debug, Clone)]
7069
pub(crate) struct CoverageSpan {
7170
pub span: Span,
72-
pub bcb_leader_bb: BasicBlock,
71+
pub bcb: BasicCoverageBlock,
7372
pub coverage_statements: Vec<CoverageStatement>,
7473
pub is_closure: bool,
7574
}
@@ -78,7 +77,7 @@ impl CoverageSpan {
7877
pub fn for_statement(
7978
statement: &Statement<'tcx>,
8079
span: Span,
81-
bcb: &BasicCoverageBlock,
80+
bcb: BasicCoverageBlock,
8281
bb: BasicBlock,
8382
stmt_index: usize,
8483
) -> Self {
@@ -92,16 +91,16 @@ impl CoverageSpan {
9291

9392
Self {
9493
span,
95-
bcb_leader_bb: bcb.leader_bb(),
94+
bcb,
9695
coverage_statements: vec![CoverageStatement::Statement(bb, span, stmt_index)],
9796
is_closure,
9897
}
9998
}
10099

101-
pub fn for_terminator(span: Span, bcb: &BasicCoverageBlock, bb: BasicBlock) -> Self {
100+
pub fn for_terminator(span: Span, bcb: BasicCoverageBlock, bb: BasicBlock) -> Self {
102101
Self {
103102
span,
104-
bcb_leader_bb: bcb.leader_bb(),
103+
bcb,
105104
coverage_statements: vec![CoverageStatement::Terminator(bb, span)],
106105
is_closure: false,
107106
}
@@ -132,7 +131,7 @@ impl CoverageSpan {
132131

133132
#[inline]
134133
pub fn is_in_same_bcb(&self, other: &Self) -> bool {
135-
self.bcb_leader_bb == other.bcb_leader_bb
134+
self.bcb == other.bcb
136135
}
137136

138137
pub fn format_coverage_statements(
@@ -164,15 +163,12 @@ pub struct CoverageSpans<'a, 'tcx> {
164163
/// The MIR, used to look up `BasicBlockData`.
165164
mir_body: &'a mir::Body<'tcx>,
166165

167-
/// A snapshot of the MIR CFG dominators before injecting any coverage statements.
168-
dominators: Dominators<BasicBlock>,
169-
170166
/// A `Span` covering the function body of the MIR (typically from left curly brace to right
171167
/// curly brace).
172168
body_span: Span,
173169

174170
/// The BasicCoverageBlock Control Flow Graph (BCB CFG).
175-
basic_coverage_blocks: &'a BasicCoverageBlocks,
171+
basic_coverage_blocks: &'a CoverageGraph,
176172

177173
/// The initial set of `CoverageSpan`s, sorted by `Span` (`lo` and `hi`) and by relative
178174
/// dominance between the `BasicCoverageBlock`s of equal `Span`s.
@@ -213,12 +209,10 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
213209
pub(crate) fn generate_coverage_spans(
214210
mir_body: &'a mir::Body<'tcx>,
215211
body_span: Span,
216-
basic_coverage_blocks: &'a BasicCoverageBlocks,
212+
basic_coverage_blocks: &'a CoverageGraph,
217213
) -> Vec<CoverageSpan> {
218-
let dominators = mir_body.dominators();
219214
let mut coverage_spans = CoverageSpans {
220215
mir_body,
221-
dominators,
222216
body_span,
223217
basic_coverage_blocks,
224218
sorted_spans_iter: None,
@@ -246,7 +240,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
246240
/// The basic steps are:
247241
///
248242
/// 1. Extract an initial set of spans from the `Statement`s and `Terminator`s of each
249-
/// `BasicCoverageBlock`.
243+
/// `BasicCoverageBlockData`.
250244
/// 2. Sort the spans by span.lo() (starting position). Spans that start at the same position
251245
/// are sorted with longer spans before shorter spans; and equal spans are sorted
252246
/// (deterministically) based on "dominator" relationship (if any).
@@ -263,8 +257,8 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
263257
/// to be).
264258
fn mir_to_initial_sorted_coverage_spans(&self) -> Vec<CoverageSpan> {
265259
let mut initial_spans = Vec::<CoverageSpan>::with_capacity(self.mir_body.num_nodes() * 2);
266-
for bcb in self.basic_coverage_blocks.iter() {
267-
for coverage_span in self.bcb_to_initial_coverage_spans(bcb) {
260+
for (bcb, bcb_data) in self.basic_coverage_blocks.iter_enumerated() {
261+
for coverage_span in self.bcb_to_initial_coverage_spans(bcb, bcb_data) {
268262
initial_spans.push(coverage_span);
269263
}
270264
}
@@ -285,7 +279,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
285279
// dominators always come after the dominated equal spans). When later
286280
// comparing two spans in order, the first will either dominate the second,
287281
// or they will have no dominator relationship.
288-
self.dominators.rank_partial_cmp(b.bcb_leader_bb, a.bcb_leader_bb)
282+
self.basic_coverage_blocks.dominators().rank_partial_cmp(b.bcb, a.bcb)
289283
}
290284
} else {
291285
// Sort hi() in reverse order so shorter spans are attempted after longer spans.
@@ -357,13 +351,13 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
357351
let mut has_coverage = BitSet::new_empty(basic_coverage_blocks.num_nodes());
358352
for covspan in &refined_spans {
359353
if !covspan.span.is_empty() {
360-
has_coverage.insert(covspan.bcb_leader_bb);
354+
has_coverage.insert(covspan.bcb);
361355
}
362356
}
363357
refined_spans.retain(|covspan| {
364358
!(covspan.span.is_empty()
365-
&& is_goto(&mir_body[covspan.bcb_leader_bb].terminator().kind)
366-
&& has_coverage.contains(covspan.bcb_leader_bb))
359+
&& is_goto(&basic_coverage_blocks[covspan.bcb].terminator(mir_body).kind)
360+
&& has_coverage.contains(covspan.bcb))
367361
});
368362

369363
// Remove `CoverageSpan`s derived from closures, originally added to ensure the coverage
@@ -374,12 +368,17 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
374368
}
375369

376370
// Generate a set of `CoverageSpan`s from the filtered set of `Statement`s and `Terminator`s of
377-
// the `BasicBlock`(s) in the given `BasicCoverageBlock`. One `CoverageSpan` is generated
371+
// the `BasicBlock`(s) in the given `BasicCoverageBlockData`. One `CoverageSpan` is generated
378372
// for each `Statement` and `Terminator`. (Note that subsequent stages of coverage analysis will
379373
// merge some `CoverageSpan`s, at which point a `CoverageSpan` may represent multiple
380374
// `Statement`s and/or `Terminator`s.)
381-
fn bcb_to_initial_coverage_spans(&self, bcb: &BasicCoverageBlock) -> Vec<CoverageSpan> {
382-
bcb.blocks
375+
fn bcb_to_initial_coverage_spans(
376+
&self,
377+
bcb: BasicCoverageBlock,
378+
bcb_data: &'a BasicCoverageBlockData,
379+
) -> Vec<CoverageSpan> {
380+
bcb_data
381+
.basic_blocks
383382
.iter()
384383
.map(|bbref| {
385384
let bb = *bbref;
@@ -636,7 +635,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
636635
}
637636

638637
fn span_bcb_is_dominated_by(&self, covspan: &CoverageSpan, dom_covspan: &CoverageSpan) -> bool {
639-
self.dominators.is_dominated_by(covspan.bcb_leader_bb, dom_covspan.bcb_leader_bb)
638+
self.basic_coverage_blocks.is_dominated_by(covspan.bcb, dom_covspan.bcb)
640639
}
641640
}
642641

src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.lazy_boolean.json

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@
1717
},
1818
"lines": {
1919
"count": 40,
20-
"covered": 32,
21-
"percent": 80
20+
"covered": 30,
21+
"percent": 75
2222
},
2323
"regions": {
24-
"count": 39,
25-
"covered": 28,
24+
"count": 37,
25+
"covered": 26,
2626
"notcovered": 11,
27-
"percent": 71.7948717948718
27+
"percent": 70.27027027027027
2828
}
2929
}
3030
}
@@ -42,14 +42,14 @@
4242
},
4343
"lines": {
4444
"count": 40,
45-
"covered": 32,
46-
"percent": 80
45+
"covered": 30,
46+
"percent": 75
4747
},
4848
"regions": {
49-
"count": 39,
50-
"covered": 28,
49+
"count": 37,
50+
"covered": 26,
5151
"notcovered": 11,
52-
"percent": 71.7948717948718
52+
"percent": 70.27027027027027
5353
}
5454
}
5555
}

src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.loops_and_branches.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@
2121
"percent": 100
2222
},
2323
"regions": {
24-
"count": 10,
24+
"count": 9,
2525
"covered": 8,
26-
"notcovered": 2,
27-
"percent": 80
26+
"notcovered": 1,
27+
"percent": 88.88888888888889
2828
}
2929
}
3030
}
@@ -46,10 +46,10 @@
4646
"percent": 100
4747
},
4848
"regions": {
49-
"count": 10,
49+
"count": 9,
5050
"covered": 8,
51-
"notcovered": 2,
52-
"percent": 80
51+
"notcovered": 1,
52+
"percent": 88.88888888888889
5353
}
5454
}
5555
}

src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.nested_loops.json

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@
1717
},
1818
"lines": {
1919
"count": 21,
20-
"covered": 17,
21-
"percent": 80.95238095238095
20+
"covered": 16,
21+
"percent": 76.19047619047619
2222
},
2323
"regions": {
24-
"count": 20,
25-
"covered": 16,
24+
"count": 18,
25+
"covered": 14,
2626
"notcovered": 4,
27-
"percent": 80
27+
"percent": 77.77777777777779
2828
}
2929
}
3030
}
@@ -42,14 +42,14 @@
4242
},
4343
"lines": {
4444
"count": 21,
45-
"covered": 17,
46-
"percent": 80.95238095238095
45+
"covered": 16,
46+
"percent": 76.19047619047619
4747
},
4848
"regions": {
49-
"count": 20,
50-
"covered": 16,
49+
"count": 18,
50+
"covered": 14,
5151
"notcovered": 4,
52-
"percent": 80
52+
"percent": 77.77777777777779
5353
}
5454
}
5555
}

0 commit comments

Comments
 (0)