Skip to content

Commit 05390e7

Browse files
committed
coverage: Represent branches as a list of arms during MIR building, too
1 parent 37e62f0 commit 05390e7

File tree

6 files changed

+72
-43
lines changed

6 files changed

+72
-43
lines changed

compiler/rustc_middle/src/mir/coverage.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -282,17 +282,21 @@ pub struct BranchInfo {
282282
/// injected into the MIR body. This makes it possible to allocate per-ID
283283
/// data structures without having to scan the entire body first.
284284
pub num_block_markers: usize,
285-
pub branch_spans: Vec<BranchSpan>,
285+
pub branch_arm_lists: Vec<Vec<BranchArm>>,
286286
pub mcdc_branch_spans: Vec<MCDCBranchSpan>,
287287
pub mcdc_decision_spans: Vec<MCDCDecisionSpan>,
288288
}
289289

290290
#[derive(Clone, Debug)]
291291
#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
292-
pub struct BranchSpan {
292+
pub struct BranchArm {
293293
pub span: Span,
294-
pub true_marker: BlockMarkerId,
295-
pub false_marker: BlockMarkerId,
294+
/// Marks the block that is jumped to after this arm's pattern matches,
295+
/// but before its guard is checked.
296+
pub pre_guard_marker: BlockMarkerId,
297+
/// Marks the block that is jumped to after this arm's guard succeeds.
298+
/// If this is equal to `pre_guard_marker`, the arm has no guard.
299+
pub arm_taken_marker: BlockMarkerId,
296300
}
297301

298302
#[derive(Copy, Clone, Debug)]

compiler/rustc_middle/src/mir/pretty.rs

+11-8
Original file line numberDiff line numberDiff line change
@@ -487,14 +487,18 @@ fn write_coverage_branch_info(
487487
branch_info: &coverage::BranchInfo,
488488
w: &mut dyn io::Write,
489489
) -> io::Result<()> {
490-
let coverage::BranchInfo { branch_spans, mcdc_branch_spans, mcdc_decision_spans, .. } =
490+
let coverage::BranchInfo { branch_arm_lists, mcdc_branch_spans, mcdc_decision_spans, .. } =
491491
branch_info;
492492

493-
for coverage::BranchSpan { span, true_marker, false_marker } in branch_spans {
494-
writeln!(
495-
w,
496-
"{INDENT}coverage branch {{ true: {true_marker:?}, false: {false_marker:?} }} => {span:?}",
497-
)?;
493+
for arms in branch_arm_lists {
494+
writeln!(w, "{INDENT}coverage branches {{")?;
495+
for coverage::BranchArm { span, pre_guard_marker, arm_taken_marker } in arms {
496+
writeln!(w, "{INDENT}{INDENT}{pre_guard_marker:?}, {arm_taken_marker:?} => {span:?}")?;
497+
}
498+
writeln!(w, "{INDENT}}}")?;
499+
}
500+
if !branch_arm_lists.is_empty() {
501+
writeln!(w)?;
498502
}
499503

500504
for coverage::MCDCBranchSpan {
@@ -521,8 +525,7 @@ fn write_coverage_branch_info(
521525
)?;
522526
}
523527

524-
if !branch_spans.is_empty() || !mcdc_branch_spans.is_empty() || !mcdc_decision_spans.is_empty()
525-
{
528+
if !mcdc_branch_spans.is_empty() || !mcdc_decision_spans.is_empty() {
526529
writeln!(w)?;
527530
}
528531

compiler/rustc_mir_build/src/build/coverageinfo.rs

+12-11
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, UnOp};
77
use rustc_middle::thir::{ExprId, ExprKind, Pat, Thir};
88
use rustc_middle::ty::TyCtxt;
@@ -18,7 +18,7 @@ pub(crate) struct BranchInfoBuilder {
1818
nots: FxHashMap<ExprId, NotInfo>,
1919

2020
markers: BlockMarkerGen,
21-
branch_spans: Vec<BranchSpan>,
21+
branch_arm_lists: Vec<Vec<BranchArm>>,
2222

2323
mcdc_info: Option<MCDCInfoBuilder>,
2424
}
@@ -70,7 +70,7 @@ impl BranchInfoBuilder {
7070
Some(Self {
7171
nots: FxHashMap::default(),
7272
markers: BlockMarkerGen::default(),
73-
branch_spans: vec![],
73+
branch_arm_lists: vec![],
7474
mcdc_info: tcx.sess.instrument_coverage_mcdc().then(MCDCInfoBuilder::new),
7575
})
7676
} else {
@@ -141,24 +141,25 @@ impl BranchInfoBuilder {
141141
let true_marker = self.markers.inject_block_marker(cfg, source_info, true_block);
142142
let false_marker = self.markers.inject_block_marker(cfg, source_info, false_block);
143143

144-
self.branch_spans.push(BranchSpan {
144+
let arm = |marker| BranchArm {
145145
span: source_info.span,
146-
true_marker,
147-
false_marker,
148-
});
146+
pre_guard_marker: marker,
147+
arm_taken_marker: marker,
148+
};
149+
self.branch_arm_lists.push(vec![arm(true_marker), arm(false_marker)]);
149150
}
150151
}
151152

152153
pub(crate) fn into_done(self) -> Option<Box<mir::coverage::BranchInfo>> {
153154
let Self {
154155
nots: _,
155156
markers: BlockMarkerGen { num_block_markers },
156-
branch_spans,
157+
branch_arm_lists,
157158
mcdc_info,
158159
} = self;
159160

160161
if num_block_markers == 0 {
161-
assert!(branch_spans.is_empty());
162+
assert!(branch_arm_lists.is_empty());
162163
return None;
163164
}
164165

@@ -167,7 +168,7 @@ impl BranchInfoBuilder {
167168

168169
Some(Box::new(mir::coverage::BranchInfo {
169170
num_block_markers,
170-
branch_spans,
171+
branch_arm_lists,
171172
mcdc_branch_spans,
172173
mcdc_decision_spans,
173174
}))
@@ -240,7 +241,7 @@ impl<'tcx> Builder<'_, 'tcx> {
240241
}
241242

242243
/// If branch coverage is enabled, inject marker statements into `then_block`
243-
/// and `else_block`, and record their IDs in the table of branch spans.
244+
/// and `else_block`, and record their IDs in the branch table.
244245
pub(crate) fn visit_coverage_branch_condition(
245246
&mut self,
246247
mut expr_id: ExprId,

compiler/rustc_mir_transform/src/coverage/mappings.rs

+31-16
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::collections::BTreeSet;
33
use rustc_data_structures::graph::DirectedGraph;
44
use rustc_index::bit_set::BitSet;
55
use rustc_index::IndexVec;
6-
use rustc_middle::mir::coverage::{BlockMarkerId, BranchSpan, ConditionInfo, CoverageKind};
6+
use rustc_middle::mir::coverage::{BlockMarkerId, ConditionInfo, CoverageKind};
77
use rustc_middle::mir::{self, BasicBlock, StatementKind};
88
use rustc_middle::ty::TyCtxt;
99
use rustc_span::Span;
@@ -193,25 +193,40 @@ pub(super) fn extract_branch_arm_lists(
193193
let block_markers = resolve_block_markers(branch_info, mir_body);
194194

195195
branch_info
196-
.branch_spans
196+
.branch_arm_lists
197197
.iter()
198-
.filter_map(|&BranchSpan { span: raw_span, true_marker, false_marker }| {
199-
// For now, ignore any branch span that was introduced by
200-
// expansion. This makes things like assert macros less noisy.
201-
if !raw_span.ctxt().outer_expn_data().is_root() {
202-
return None;
198+
.filter_map(|arms| {
199+
let mut bcb_arms = Vec::with_capacity(arms.len());
200+
201+
// If any arm can't be resolved, return None to skip the entire list
202+
// of arms that contains it.
203+
for &mir::coverage::BranchArm { span: raw_span, pre_guard_marker, arm_taken_marker } in
204+
arms
205+
{
206+
// For now, ignore any branch span that was introduced by
207+
// expansion. This makes things like assert macros less noisy.
208+
if !raw_span.ctxt().outer_expn_data().is_root() {
209+
return None;
210+
}
211+
212+
let (span, _) =
213+
unexpand_into_body_span_with_visible_macro(raw_span, hir_info.body_span)?;
214+
215+
let pre_guard_bcb =
216+
basic_coverage_blocks.bcb_from_bb(block_markers[pre_guard_marker]?)?;
217+
let arm_taken_bcb =
218+
basic_coverage_blocks.bcb_from_bb(block_markers[arm_taken_marker]?)?;
219+
220+
bcb_arms.push(BranchArm { span, pre_guard_bcb, arm_taken_bcb });
203221
}
204-
let (span, _) =
205-
unexpand_into_body_span_with_visible_macro(raw_span, hir_info.body_span)?;
206-
207-
let bcb_from_marker =
208-
|marker: BlockMarkerId| basic_coverage_blocks.bcb_from_bb(block_markers[marker]?);
222+
assert_eq!(arms.len(), bcb_arms.len());
209223

210-
let true_bcb = bcb_from_marker(true_marker)?;
211-
let false_bcb = bcb_from_marker(false_marker)?;
224+
if bcb_arms.len() < 2 {
225+
debug_assert!(false, "MIR building shouldn't create branches with <2 arms");
226+
return None;
227+
}
212228

213-
let arm = |bcb| BranchArm { span, pre_guard_bcb: bcb, arm_taken_bcb: bcb };
214-
Some(vec![arm(true_bcb), arm(false_bcb)])
229+
Some(bcb_arms)
215230
})
216231
.collect::<Vec<_>>()
217232
}

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

+5-2
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,17 @@
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), BlockMarkerId(0) => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0)
10+
BlockMarkerId(1), 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) };
14+
coverage Branch { true_term: Expression(0), false_term: Counter(1) } => $DIR/instrument_coverage_cleanup.rs:14:8 - 14:36;
1115
coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:13:1 - 14:36;
1216
coverage Code(Expression(0)) => $DIR/instrument_coverage_cleanup.rs:14:37 - 14:39;
1317
coverage Code(Counter(1)) => $DIR/instrument_coverage_cleanup.rs:14:39 - 14:40;
1418
coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:15:1 - 15:2;
15-
coverage Branch { true_term: Expression(0), false_term: Counter(1) } => $DIR/instrument_coverage_cleanup.rs:14:8 - 14:36;
1619

1720
bb0: {
1821
Coverage::CounterIncrement(0);

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

+5-2
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,17 @@
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), BlockMarkerId(0) => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0)
10+
BlockMarkerId(1), 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) };
14+
+ coverage Branch { true_term: Expression(0), false_term: Counter(1) } => $DIR/instrument_coverage_cleanup.rs:14:8 - 14:36;
1115
+ coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:13:1 - 14:36;
1216
+ coverage Code(Expression(0)) => $DIR/instrument_coverage_cleanup.rs:14:37 - 14:39;
1317
+ coverage Code(Counter(1)) => $DIR/instrument_coverage_cleanup.rs:14:39 - 14:40;
1418
+ coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:15:1 - 15:2;
15-
+ coverage Branch { true_term: Expression(0), false_term: Counter(1) } => $DIR/instrument_coverage_cleanup.rs:14:8 - 14:36;
1619
+
1720
bb0: {
1821
+ Coverage::CounterIncrement(0);

0 commit comments

Comments
 (0)