Skip to content

Commit 67a774a

Browse files
committed
coverage: Represent branches as a list of arms during MIR building, too
1 parent 556eaf8 commit 67a774a

File tree

6 files changed

+71
-38
lines changed

6 files changed

+71
-38
lines changed

compiler/rustc_middle/src/mir/coverage.rs

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

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

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

compiler/rustc_middle/src/mir/pretty.rs

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

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

499503
for coverage::MCDCBranchSpan { span, condition_info, true_marker, false_marker } in
@@ -513,8 +517,7 @@ fn write_coverage_branch_info(
513517
)?;
514518
}
515519

516-
if !branch_spans.is_empty() || !mcdc_branch_spans.is_empty() || !mcdc_decision_spans.is_empty()
517-
{
520+
if !mcdc_branch_spans.is_empty() || !mcdc_decision_spans.is_empty() {
518521
writeln!(w)?;
519522
}
520523

compiler/rustc_mir_build/src/build/coverageinfo.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::collections::VecDeque;
44

55
use rustc_data_structures::fx::FxHashMap;
66
use rustc_middle::mir::coverage::{
7-
BlockMarkerId, BranchSpan, ConditionId, ConditionInfo, CoverageKind, MCDCBranchSpan,
7+
BlockMarkerId, BranchArm, ConditionId, ConditionInfo, CoverageKind, MCDCBranchSpan,
88
MCDCDecisionSpan,
99
};
1010
use rustc_middle::mir::{self, BasicBlock, SourceInfo, UnOp};
@@ -21,7 +21,7 @@ pub(crate) struct BranchInfoBuilder {
2121
nots: FxHashMap<ExprId, NotInfo>,
2222

2323
num_block_markers: usize,
24-
branch_spans: Vec<BranchSpan>,
24+
branch_arm_lists: Vec<Vec<BranchArm>>,
2525

2626
mcdc_branch_spans: Vec<MCDCBranchSpan>,
2727
mcdc_decision_spans: Vec<MCDCDecisionSpan>,
@@ -46,7 +46,7 @@ impl BranchInfoBuilder {
4646
Some(Self {
4747
nots: FxHashMap::default(),
4848
num_block_markers: 0,
49-
branch_spans: vec![],
49+
branch_arm_lists: vec![],
5050
mcdc_branch_spans: vec![],
5151
mcdc_decision_spans: vec![],
5252
mcdc_state: MCDCState::new_if_enabled(tcx),
@@ -144,7 +144,12 @@ impl BranchInfoBuilder {
144144
let true_marker = self.inject_block_marker(cfg, source_info, true_block);
145145
let false_marker = self.inject_block_marker(cfg, source_info, false_block);
146146

147-
self.branch_spans.push(BranchSpan { span: source_info.span, true_marker, false_marker });
147+
let arm = |marker| BranchArm {
148+
span: source_info.span,
149+
pre_guard_marker: marker,
150+
arm_taken_marker: marker,
151+
};
152+
self.branch_arm_lists.push(vec![arm(true_marker), arm(false_marker)]);
148153
}
149154

150155
fn next_block_marker_id(&mut self) -> BlockMarkerId {
@@ -174,20 +179,20 @@ impl BranchInfoBuilder {
174179
let Self {
175180
nots: _,
176181
num_block_markers,
177-
branch_spans,
182+
branch_arm_lists,
178183
mcdc_branch_spans,
179184
mcdc_decision_spans,
180185
mcdc_state: _,
181186
} = self;
182187

183188
if num_block_markers == 0 {
184-
assert!(branch_spans.is_empty());
189+
assert!(branch_arm_lists.is_empty());
185190
return None;
186191
}
187192

188193
Some(Box::new(mir::coverage::BranchInfo {
189194
num_block_markers,
190-
branch_spans,
195+
branch_arm_lists,
191196
mcdc_branch_spans,
192197
mcdc_decision_spans,
193198
}))
@@ -337,7 +342,7 @@ impl MCDCState {
337342

338343
impl Builder<'_, '_> {
339344
/// If branch coverage is enabled, inject marker statements into `then_block`
340-
/// and `else_block`, and record their IDs in the table of branch spans.
345+
/// and `else_block`, and record their IDs in the table of branches.
341346
pub(crate) fn visit_coverage_branch_condition(
342347
&mut self,
343348
mut expr_id: ExprId,

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

+29-16
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use rustc_data_structures::captures::Captures;
22
use rustc_data_structures::fx::FxHashSet;
33
use rustc_index::IndexVec;
44
use rustc_middle::mir::coverage::{
5-
BlockMarkerId, BranchSpan, CoverageKind, MCDCBranchSpan, MCDCDecisionSpan,
5+
BlockMarkerId, BranchArm, CoverageKind, MCDCBranchSpan, MCDCDecisionSpan,
66
};
77
use rustc_middle::mir::{
88
self, AggregateKind, BasicBlock, FakeReadCause, Rvalue, Statement, StatementKind, Terminator,
@@ -403,25 +403,38 @@ pub(super) fn extract_branch_arm_lists(
403403
let block_markers = resolve_block_markers(branch_info, mir_body);
404404

405405
branch_info
406-
.branch_spans
406+
.branch_arm_lists
407407
.iter()
408-
.filter_map(|&BranchSpan { span: raw_span, true_marker, false_marker }| {
409-
// For now, ignore any branch span that was introduced by
410-
// expansion. This makes things like assert macros less noisy.
411-
if !raw_span.ctxt().outer_expn_data().is_root() {
412-
return None;
413-
}
414-
let (span, _) =
415-
unexpand_into_body_span_with_visible_macro(raw_span, hir_info.body_span)?;
408+
.filter_map(|arms| {
409+
let mut bcb_arms = Vec::with_capacity(arms.len());
410+
411+
// If any arm can't be resolved, return None to skip the entire list
412+
// of arms that contains it.
413+
for &BranchArm { span: raw_span, pre_guard_marker, arm_taken_marker } in arms {
414+
// For now, ignore any branch span that was introduced by
415+
// expansion. This makes things like assert macros less noisy.
416+
if !raw_span.ctxt().outer_expn_data().is_root() {
417+
return None;
418+
}
416419

417-
let bcb_from_marker =
418-
|marker: BlockMarkerId| basic_coverage_blocks.bcb_from_bb(block_markers[marker]?);
420+
let (span, _) =
421+
unexpand_into_body_span_with_visible_macro(raw_span, hir_info.body_span)?;
419422

420-
let true_bcb = bcb_from_marker(true_marker)?;
421-
let false_bcb = bcb_from_marker(false_marker)?;
423+
let pre_guard_bcb =
424+
basic_coverage_blocks.bcb_from_bb(block_markers[pre_guard_marker]?)?;
425+
let arm_taken_bcb =
426+
basic_coverage_blocks.bcb_from_bb(block_markers[arm_taken_marker]?)?;
427+
428+
bcb_arms.push(BcbBranchArm { span, pre_guard_bcb, arm_taken_bcb });
429+
}
430+
assert_eq!(arms.len(), bcb_arms.len());
431+
432+
if bcb_arms.len() < 2 {
433+
debug_assert!(false, "MIR building shouldn't create branches with <2 arms");
434+
return None;
435+
}
422436

423-
let arm = |bcb| BcbBranchArm { span, pre_guard_bcb: bcb, arm_taken_bcb: bcb };
424-
Some(vec![arm(true_bcb), arm(false_bcb)])
437+
Some(bcb_arms)
425438
})
426439
.collect::<Vec<_>>()
427440
}

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)