Skip to content

Commit 1b324bd

Browse files
committed
coverage: Represent branches as a list of arms during MIR building, too
1 parent e03b5f5 commit 1b324bd

File tree

7 files changed

+62
-37
lines changed

7 files changed

+62
-37
lines changed

compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,15 @@ impl<'tcx> FunctionCoverageCollector<'tcx> {
6565
// For each expression ID that is directly used by one or more mappings,
6666
// mark it as not-yet-seen. This indicates that we expect to see a
6767
// corresponding `ExpressionUsed` statement during MIR traversal.
68-
for term in function_coverage_info.mappings.iter().flat_map(|m| m.kind.terms()) {
68+
for term in function_coverage_info
69+
.mappings
70+
.iter()
71+
// For many-armed branches, some branch mappings will have expressions
72+
// that don't correspond to any node in the control-flow graph, so don't
73+
// expect to see `ExpressionUsed` statements for them.
74+
.filter(|m| !matches!(m.kind, MappingKind::Branch { .. }))
75+
.flat_map(|m| m.kind.terms())
76+
{
6977
if let CovTerm::Expression(id) = term {
7078
expressions_seen.remove(id);
7179
}

compiler/rustc_middle/src/mir/coverage.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -225,13 +225,12 @@ pub struct BranchInfo {
225225
/// injected into the MIR body. This makes it possible to allocate per-ID
226226
/// data structures without having to scan the entire body first.
227227
pub num_block_markers: usize,
228-
pub branch_spans: Vec<BranchSpan>,
228+
pub branch_arm_lists: Vec<Vec<BranchArm>>,
229229
}
230230

231231
#[derive(Clone, Debug)]
232232
#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
233-
pub struct BranchSpan {
233+
pub struct BranchArm {
234234
pub span: Span,
235-
pub true_marker: BlockMarkerId,
236-
pub false_marker: BlockMarkerId,
235+
pub marker: BlockMarkerId,
237236
}

compiler/rustc_middle/src/mir/pretty.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -475,15 +475,16 @@ fn write_coverage_branch_info(
475475
branch_info: &coverage::BranchInfo,
476476
w: &mut dyn io::Write,
477477
) -> io::Result<()> {
478-
let coverage::BranchInfo { branch_spans, .. } = branch_info;
478+
let coverage::BranchInfo { branch_arm_lists, .. } = branch_info;
479479

480-
for coverage::BranchSpan { span, true_marker, false_marker } in branch_spans {
481-
writeln!(
482-
w,
483-
"{INDENT}coverage branch {{ true: {true_marker:?}, false: {false_marker:?} }} => {span:?}",
484-
)?;
480+
for arms in branch_arm_lists {
481+
writeln!(w, "{INDENT}coverage branches {{")?;
482+
for coverage::BranchArm { span, marker } in arms {
483+
writeln!(w, "{INDENT}{INDENT}{marker:?} => {span:?}")?;
484+
}
485+
writeln!(w, "{INDENT}}}")?;
485486
}
486-
if !branch_spans.is_empty() {
487+
if !branch_arm_lists.is_empty() {
487488
writeln!(w)?;
488489
}
489490

compiler/rustc_mir_build/src/build/coverageinfo.rs

+15-8
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::assert_matches::assert_matches;
22
use std::collections::hash_map::Entry;
33

44
use rustc_data_structures::fx::FxHashMap;
5-
use rustc_middle::mir::coverage::{BlockMarkerId, BranchSpan, CoverageKind};
5+
use rustc_middle::mir::coverage::{BlockMarkerId, BranchArm, CoverageKind};
66
use rustc_middle::mir::{self, BasicBlock, SourceInfo, SourceScope, UnOp};
77
use rustc_middle::thir::{ExprId, ExprKind, Thir};
88
use rustc_middle::ty::TyCtxt;
@@ -15,7 +15,7 @@ pub(crate) struct BranchInfoBuilder {
1515
nots: FxHashMap<ExprId, NotInfo>,
1616

1717
num_block_markers: usize,
18-
branch_spans: Vec<BranchSpan>,
18+
branch_arm_lists: Vec<Vec<BranchArm>>,
1919
}
2020

2121
#[derive(Clone, Copy)]
@@ -33,7 +33,11 @@ impl BranchInfoBuilder {
3333
/// is enabled and `def_id` represents a function that is eligible for coverage.
3434
pub(crate) fn new_if_enabled(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<Self> {
3535
if tcx.sess.instrument_coverage_branch() && tcx.is_eligible_for_coverage(def_id) {
36-
Some(Self { nots: FxHashMap::default(), num_block_markers: 0, branch_spans: vec![] })
36+
Some(Self {
37+
nots: FxHashMap::default(),
38+
num_block_markers: 0,
39+
branch_arm_lists: vec![],
40+
})
3741
} else {
3842
None
3943
}
@@ -102,7 +106,10 @@ impl BranchInfoBuilder {
102106
let true_marker = self.inject_block_marker(cfg, source_info, then_block);
103107
let false_marker = self.inject_block_marker(cfg, source_info, else_block);
104108

105-
self.branch_spans.push(BranchSpan { span, true_marker, false_marker });
109+
self.branch_arm_lists.push(vec![
110+
BranchArm { span, marker: true_marker },
111+
BranchArm { span, marker: false_marker },
112+
]);
106113
}
107114

108115
fn next_block_marker_id(&mut self) -> BlockMarkerId {
@@ -129,20 +136,20 @@ impl BranchInfoBuilder {
129136
}
130137

131138
pub(crate) fn into_done(self) -> Option<Box<mir::coverage::BranchInfo>> {
132-
let Self { nots: _, num_block_markers, branch_spans } = self;
139+
let Self { nots: _, num_block_markers, branch_arm_lists } = self;
133140

134141
if num_block_markers == 0 {
135-
assert!(branch_spans.is_empty());
142+
assert!(branch_arm_lists.is_empty());
136143
return None;
137144
}
138145

139-
Some(Box::new(mir::coverage::BranchInfo { num_block_markers, branch_spans }))
146+
Some(Box::new(mir::coverage::BranchInfo { num_block_markers, branch_arm_lists }))
140147
}
141148
}
142149

143150
impl Builder<'_, '_> {
144151
/// If branch coverage is enabled, inject marker statements into `then_block`
145-
/// and `else_block`, and record their IDs in the table of branch spans.
152+
/// and `else_block`, and record their IDs in the table of branches.
146153
pub(crate) fn visit_coverage_branch_condition(
147154
&mut self,
148155
expr_id: ExprId,

compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs

+17-15
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use rustc_data_structures::captures::Captures;
22
use rustc_data_structures::fx::FxHashSet;
33
use rustc_index::IndexVec;
4-
use rustc_middle::mir::coverage::{BlockMarkerId, BranchSpan, CoverageKind};
4+
use rustc_middle::mir::coverage::{BlockMarkerId, BranchArm, CoverageKind};
55
use rustc_middle::mir::{
66
self, AggregateKind, BasicBlock, FakeReadCause, Rvalue, Statement, StatementKind, Terminator,
77
TerminatorKind,
@@ -382,24 +382,26 @@ pub(super) fn extract_branch_arm_lists(
382382
}
383383

384384
branch_info
385-
.branch_spans
385+
.branch_arm_lists
386386
.iter()
387-
.filter_map(|&BranchSpan { span: raw_span, true_marker, false_marker }| {
388-
// For now, ignore any branch span that was introduced by
389-
// expansion. This makes things like assert macros less noisy.
390-
if !raw_span.ctxt().outer_expn_data().is_root() {
391-
return None;
392-
}
393-
let (span, _) =
394-
unexpand_into_body_span_with_visible_macro(raw_span, hir_info.body_span)?;
387+
.filter_map(|arms| {
388+
let mut bcb_arms = vec![];
389+
for &BranchArm { span: raw_span, marker } in arms {
390+
// For now, ignore any branch span that was introduced by
391+
// expansion. This makes things like assert macros less noisy.
392+
if !raw_span.ctxt().outer_expn_data().is_root() {
393+
return None;
394+
}
395395

396-
let bcb_from_marker =
397-
|marker: BlockMarkerId| basic_coverage_blocks.bcb_from_bb(block_markers[marker]?);
396+
let (span, _) =
397+
unexpand_into_body_span_with_visible_macro(raw_span, hir_info.body_span)?;
398398

399-
let true_bcb = bcb_from_marker(true_marker)?;
400-
let false_bcb = bcb_from_marker(false_marker)?;
399+
let bcb = basic_coverage_blocks.bcb_from_bb(block_markers[marker]?)?;
400+
401+
bcb_arms.push(BcbBranchArm { span, bcb });
402+
}
401403

402-
Some(vec![BcbBranchArm { span, bcb: true_bcb }, BcbBranchArm { span, bcb: false_bcb }])
404+
(bcb_arms.len() >= 2).then_some(bcb_arms)
403405
})
404406
.collect::<Vec<_>>()
405407
}

tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff

+5-1
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@
55
let mut _0: ();
66
let mut _1: bool;
77

8-
coverage branch { true: BlockMarkerId(0), false: BlockMarkerId(1) } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0)
8+
coverage branches {
9+
BlockMarkerId(0) => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0)
10+
BlockMarkerId(1) => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0)
11+
}
912

1013
coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Subtract, rhs: Counter(1) };
1114
coverage ExpressionId(1) => Expression { lhs: Counter(1), op: Add, rhs: Expression(0) };
15+
coverage ExpressionId(2) => Expression { lhs: Expression(0), op: Add, rhs: Counter(1) };
1216
coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:13:1 - 14:36;
1317
coverage Code(Expression(0)) => $DIR/instrument_coverage_cleanup.rs:14:37 - 14:39;
1418
coverage Code(Counter(1)) => $DIR/instrument_coverage_cleanup.rs:14:39 - 14:40;

tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff

+5-1
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@
55
let mut _0: ();
66
let mut _1: bool;
77

8-
coverage branch { true: BlockMarkerId(0), false: BlockMarkerId(1) } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0)
8+
coverage branches {
9+
BlockMarkerId(0) => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0)
10+
BlockMarkerId(1) => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0)
11+
}
912

1013
+ coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Subtract, rhs: Counter(1) };
1114
+ coverage ExpressionId(1) => Expression { lhs: Counter(1), op: Add, rhs: Expression(0) };
15+
+ coverage ExpressionId(2) => Expression { lhs: Expression(0), op: Add, rhs: Counter(1) };
1216
+ coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:13:1 - 14:36;
1317
+ coverage Code(Expression(0)) => $DIR/instrument_coverage_cleanup.rs:14:37 - 14:39;
1418
+ coverage Code(Counter(1)) => $DIR/instrument_coverage_cleanup.rs:14:39 - 14:40;

0 commit comments

Comments
 (0)