Skip to content

Commit 9190c63

Browse files
Zalatharranger-ross
authored andcommitted
coverage: Treat each match arm as a "branch" for branch coverage
1 parent d592166 commit 9190c63

File tree

13 files changed

+308
-80
lines changed

13 files changed

+308
-80
lines changed

compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -203,11 +203,7 @@ impl<'tcx> FunctionCoverage<'tcx> {
203203
/// Return the source hash, generated from the HIR node structure, and used to indicate whether
204204
/// or not the source code structure changed between different compilations.
205205
pub(crate) fn source_hash(&self) -> u64 {
206-
if self.is_used {
207-
self.function_coverage_info.function_source_hash
208-
} else {
209-
0
210-
}
206+
if self.is_used { self.function_coverage_info.function_source_hash } else { 0 }
211207
}
212208

213209
/// Returns an iterator over all filenames used by this function's mappings.
@@ -251,11 +247,7 @@ impl<'tcx> FunctionCoverage<'tcx> {
251247
}
252248

253249
fn counter_for_term(&self, term: CovTerm) -> Counter {
254-
if self.is_zero_term(term) {
255-
Counter::ZERO
256-
} else {
257-
Counter::from_term(term)
258-
}
250+
if self.is_zero_term(term) { Counter::ZERO } else { Counter::from_term(term) }
259251
}
260252

261253
fn is_zero_term(&self, term: CovTerm) -> bool {

compiler/rustc_middle/src/mir/pretty.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1743,13 +1743,12 @@ pub fn write_allocation_bytes<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
17431743
}
17441744
} else if let Some(prov) = alloc.provenance().get(i, &tcx) {
17451745
// Memory with provenance must be defined
1746-
assert!(alloc
1747-
.init_mask()
1748-
.is_range_initialized(alloc_range(i, Size::from_bytes(1)))
1749-
.is_ok());
1746+
assert!(
1747+
alloc.init_mask().is_range_initialized(alloc_range(i, Size::from_bytes(1))).is_ok()
1748+
);
17501749
ascii.push('━'); // HEAVY HORIZONTAL
1751-
// We have two characters to display this, which is obviously not enough.
1752-
// Format is similar to "oversized" above.
1750+
// We have two characters to display this, which is obviously not enough.
1751+
// Format is similar to "oversized" above.
17531752
let j = i.bytes_usize();
17541753
let c = alloc.inspect_with_uninit_and_ptr_outside_interpreter(j..j + 1)[0];
17551754
write!(w, "╾{c:02x}{prov:#?} (1 ptr byte)╼")?;

compiler/rustc_mir_build/src/build/coverageinfo.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ struct NotInfo {
4343
is_flipped: bool,
4444
}
4545

46+
pub(crate) struct MatchArm {
47+
pub(crate) source_info: SourceInfo,
48+
pub(crate) pre_binding_block: Option<BasicBlock>,
49+
pub(crate) arm_block: BasicBlock,
50+
}
51+
4652
#[derive(Default)]
4753
struct BlockMarkerGen {
4854
num_block_markers: usize,
@@ -169,6 +175,34 @@ impl CoverageInfoBuilder {
169175
}
170176
}
171177

178+
pub(crate) fn add_match_arms(&mut self, cfg: &mut CFG<'_>, arms: &[MatchArm]) {
179+
// Match expressions with 0-1 arms don't have any branches for their arms.
180+
if arms.len() < 2 {
181+
return;
182+
}
183+
184+
// FIXME(#124118) The current implementation of branch coverage for
185+
// match arms can't handle or-patterns.
186+
if arms.iter().any(|arm| arm.pre_binding_block.is_none()) {
187+
return;
188+
}
189+
190+
let branch_arms = arms
191+
.iter()
192+
.map(|&MatchArm { source_info, pre_binding_block, arm_block }| {
193+
let pre_guard_marker =
194+
self.markers.inject_block_marker(cfg, source_info, pre_binding_block.unwrap());
195+
let arm_taken_marker =
196+
self.markers.inject_block_marker(cfg, source_info, arm_block);
197+
BranchArm { span: source_info.span, pre_guard_marker, arm_taken_marker }
198+
})
199+
.collect::<Vec<_>>();
200+
201+
if let Some(branch_info) = self.branch_info.as_mut() {
202+
branch_info.branch_arm_lists.push(branch_arms);
203+
}
204+
}
205+
172206
pub(crate) fn into_done(self) -> Box<CoverageInfoHi> {
173207
let Self { nots: _, markers: BlockMarkerGen { num_block_markers }, branch_info, mcdc_info } =
174208
self;

compiler/rustc_mir_build/src/build/matches/mod.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::build::ForGuard::{self, OutsideGuard, RefWithinGuard};
2222
use crate::build::expr::as_place::PlaceBuilder;
2323
use crate::build::scope::DropKind;
2424
use crate::build::{
25-
BlockAnd, BlockAndExtension, Builder, GuardFrame, GuardFrameLocal, LocalsForNode,
25+
BlockAnd, BlockAndExtension, Builder, GuardFrame, GuardFrameLocal, LocalsForNode, coverageinfo,
2626
};
2727

2828
// helper functions, broken out by category:
@@ -416,7 +416,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
416416
where
417417
'tcx: 'pat,
418418
{
419-
let arm_end_blocks: Vec<BasicBlock> = arms
419+
let mut coverage_match_arms = self.coverage_info.is_some().then_some(vec![]);
420+
421+
let arm_end_blocks: Vec<_> = arms
420422
.into_iter()
421423
.zip(built_match_tree.branches)
422424
.map(|(arm, branch)| {
@@ -451,6 +453,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
451453
opt_scrutinee_place,
452454
);
453455

456+
// FIXME: Propagate this info down to codegen
457+
let pre_binding_block = branch.sub_branches[0].otherwise_block;
458+
454459
let arm_block = this.bind_pattern(
455460
outer_source_info,
456461
branch,
@@ -460,6 +465,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
460465
EmitStorageLive::Yes,
461466
);
462467

468+
if let Some(coverage_match_arms) = coverage_match_arms.as_mut() {
469+
coverage_match_arms.push(coverageinfo::MatchArm {
470+
source_info: this.source_info(arm.pattern.span),
471+
pre_binding_block: Some(pre_binding_block),
472+
arm_block,
473+
})
474+
}
475+
463476
this.fixed_temps_scope = old_dedup_scope;
464477

465478
if let Some(source_scope) = scope {
@@ -472,6 +485,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
472485
})
473486
.collect();
474487

488+
if let Some(coverage_match_arms) = coverage_match_arms {
489+
self.coverage_info
490+
.as_mut()
491+
.expect("checked when creating `coverage_match_arms`")
492+
.add_match_arms(&mut self.cfg, &coverage_match_arms);
493+
}
494+
475495
// all the arm blocks will rejoin here
476496
let end_block = self.cfg.start_new_block();
477497

compiler/rustc_mir_transform/src/coverage/mappings.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ use std::collections::BTreeSet;
33
use rustc_data_structures::graph::DirectedGraph;
44
use rustc_index::IndexVec;
55
use rustc_index::bit_set::BitSet;
6-
use rustc_middle::mir::coverage::{
7-
BlockMarkerId, ConditionInfo, CoverageInfoHi, CoverageKind,
8-
};
6+
use rustc_middle::mir::coverage::{BlockMarkerId, ConditionInfo, CoverageInfoHi, CoverageKind};
97
use rustc_middle::mir::{self, BasicBlock, StatementKind};
108
use rustc_middle::ty::TyCtxt;
119
use rustc_span::Span;
Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,35 @@
11
Function name: guard_simple::never_taken
2-
Raw bytes (56): 0x[01, 01, 04, 01, 05, 11, 09, 0f, 0d, 05, 09, 08, 01, 08, 01, 02, 1e, 20, 05, 02, 02, 0e, 00, 1e, 05, 00, 22, 00, 24, 11, 01, 0e, 00, 1e, 20, 09, 06, 00, 0e, 00, 1e, 09, 00, 22, 00, 24, 0d, 01, 0e, 00, 10, 0b, 02, 01, 00, 02]
2+
Raw bytes (80): 0x[01, 01, 09, 07, 01, 17, 05, 0d, 09, 01, 05, 17, 11, 0d, 09, 11, 09, 23, 0d, 05, 09, 0a, 01, 08, 01, 02, 1e, 20, 01, 02, 02, 09, 00, 0a, 20, 05, 0e, 00, 0e, 00, 1e, 05, 00, 22, 00, 24, 20, 11, 12, 01, 09, 00, 0a, 11, 00, 0e, 00, 1e, 20, 09, 1a, 00, 0e, 00, 1e, 09, 00, 22, 00, 24, 0d, 01, 0e, 00, 10, 1f, 02, 01, 00, 02]
33
Number of files: 1
44
- file 0 => global file 1
5-
Number of expressions: 4
6-
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
7-
- expression 1 operands: lhs = Counter(4), rhs = Counter(2)
8-
- expression 2 operands: lhs = Expression(3, Add), rhs = Counter(3)
9-
- expression 3 operands: lhs = Counter(1), rhs = Counter(2)
10-
Number of file 0 mappings: 8
5+
Number of expressions: 9
6+
- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(0)
7+
- expression 1 operands: lhs = Expression(5, Add), rhs = Counter(1)
8+
- expression 2 operands: lhs = Counter(3), rhs = Counter(2)
9+
- expression 3 operands: lhs = Counter(0), rhs = Counter(1)
10+
- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(4)
11+
- expression 5 operands: lhs = Counter(3), rhs = Counter(2)
12+
- expression 6 operands: lhs = Counter(4), rhs = Counter(2)
13+
- expression 7 operands: lhs = Expression(8, Add), rhs = Counter(3)
14+
- expression 8 operands: lhs = Counter(1), rhs = Counter(2)
15+
Number of file 0 mappings: 10
1116
- Code(Counter(0)) at (prev + 8, 1) to (start + 2, 30)
12-
- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 2, 14) to (start + 0, 30)
17+
- Branch { true: Counter(0), false: Expression(0, Sub) } at (prev + 2, 9) to (start + 0, 10)
18+
true = c0
19+
false = (((c3 + c2) + c1) - c0)
20+
- Branch { true: Counter(1), false: Expression(3, Sub) } at (prev + 0, 14) to (start + 0, 30)
1321
true = c1
1422
false = (c0 - c1)
1523
- Code(Counter(1)) at (prev + 0, 34) to (start + 0, 36)
16-
- Code(Counter(4)) at (prev + 1, 14) to (start + 0, 30)
17-
- Branch { true: Counter(2), false: Expression(1, Sub) } at (prev + 0, 14) to (start + 0, 30)
24+
- Branch { true: Counter(4), false: Expression(4, Sub) } at (prev + 1, 9) to (start + 0, 10)
25+
true = c4
26+
false = ((c3 + c2) - c4)
27+
- Code(Counter(4)) at (prev + 0, 14) to (start + 0, 30)
28+
- Branch { true: Counter(2), false: Expression(6, Sub) } at (prev + 0, 14) to (start + 0, 30)
1829
true = c2
1930
false = (c4 - c2)
2031
- Code(Counter(2)) at (prev + 0, 34) to (start + 0, 36)
2132
- Code(Counter(3)) at (prev + 1, 14) to (start + 0, 16)
22-
- Code(Expression(2, Add)) at (prev + 2, 1) to (start + 0, 2)
33+
- Code(Expression(7, Add)) at (prev + 2, 1) to (start + 0, 2)
2334
= ((c1 + c2) + c3)
2435

tests/coverage/branch/guard-simple.coverage

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@
1010
LL| 1| _ if black_box(false) => {}
1111
^0
1212
------------------
13+
| Branch (LL:9): [True: 1, False: 0]
1314
| Branch (LL:14): [True: 0, False: 1]
1415
------------------
1516
LL| 1| _ if black_box(false) => {}
1617
^0
1718
------------------
19+
| Branch (LL:9): [True: 1, False: 0]
1820
| Branch (LL:14): [True: 0, False: 1]
1921
------------------
2022
LL| 1| _ => {}

tests/coverage/branch/guard.cov-map

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,48 @@
11
Function name: guard::branch_match_guard
2-
Raw bytes (85): 0x[01, 01, 06, 19, 0d, 05, 09, 0f, 15, 13, 11, 17, 0d, 05, 09, 0d, 01, 0c, 01, 01, 10, 1d, 03, 0b, 00, 0c, 15, 01, 14, 02, 0a, 0d, 03, 0e, 00, 0f, 19, 00, 14, 00, 19, 20, 0d, 02, 00, 14, 00, 1e, 0d, 00, 1d, 02, 0a, 11, 03, 0e, 00, 0f, 1d, 00, 14, 00, 19, 20, 11, 09, 00, 14, 00, 1e, 11, 00, 1d, 02, 0a, 17, 03, 0e, 02, 0a, 0b, 04, 01, 00, 02]
2+
Raw bytes (120): 0x[01, 01, 0d, 1b, 0d, 33, 11, 05, 09, 03, 19, 19, 0d, 1b, 1d, 33, 11, 05, 09, 05, 09, 2b, 15, 2f, 11, 33, 0d, 05, 09, 10, 01, 0c, 01, 01, 10, 1d, 03, 0b, 00, 0c, 20, 15, 03, 01, 09, 00, 10, 15, 00, 14, 02, 0a, 20, 19, 0e, 03, 09, 00, 10, 0d, 00, 0e, 00, 0f, 19, 00, 14, 00, 19, 20, 0d, 12, 00, 14, 00, 1e, 0d, 00, 1d, 02, 0a, 20, 1d, 16, 03, 09, 00, 10, 11, 00, 0e, 00, 0f, 1d, 00, 14, 00, 19, 20, 11, 09, 00, 14, 00, 1e, 11, 00, 1d, 02, 0a, 33, 03, 0e, 02, 0a, 27, 04, 01, 00, 02]
33
Number of files: 1
44
- file 0 => global file 1
5-
Number of expressions: 6
6-
- expression 0 operands: lhs = Counter(6), rhs = Counter(3)
7-
- expression 1 operands: lhs = Counter(1), rhs = Counter(2)
8-
- expression 2 operands: lhs = Expression(3, Add), rhs = Counter(5)
9-
- expression 3 operands: lhs = Expression(4, Add), rhs = Counter(4)
10-
- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(3)
11-
- expression 5 operands: lhs = Counter(1), rhs = Counter(2)
12-
Number of file 0 mappings: 13
5+
Number of expressions: 13
6+
- expression 0 operands: lhs = Expression(6, Add), rhs = Counter(3)
7+
- expression 1 operands: lhs = Expression(12, Add), rhs = Counter(4)
8+
- expression 2 operands: lhs = Counter(1), rhs = Counter(2)
9+
- expression 3 operands: lhs = Expression(0, Add), rhs = Counter(6)
10+
- expression 4 operands: lhs = Counter(6), rhs = Counter(3)
11+
- expression 5 operands: lhs = Expression(6, Add), rhs = Counter(7)
12+
- expression 6 operands: lhs = Expression(12, Add), rhs = Counter(4)
13+
- expression 7 operands: lhs = Counter(1), rhs = Counter(2)
14+
- expression 8 operands: lhs = Counter(1), rhs = Counter(2)
15+
- expression 9 operands: lhs = Expression(10, Add), rhs = Counter(5)
16+
- expression 10 operands: lhs = Expression(11, Add), rhs = Counter(4)
17+
- expression 11 operands: lhs = Expression(12, Add), rhs = Counter(3)
18+
- expression 12 operands: lhs = Counter(1), rhs = Counter(2)
19+
Number of file 0 mappings: 16
1320
- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16)
1421
- Code(Counter(7)) at (prev + 3, 11) to (start + 0, 12)
15-
- Code(Counter(5)) at (prev + 1, 20) to (start + 2, 10)
16-
- Code(Counter(3)) at (prev + 3, 14) to (start + 0, 15)
22+
- Branch { true: Counter(5), false: Expression(0, Add) } at (prev + 1, 9) to (start + 0, 16)
23+
true = c5
24+
false = (((c1 + c2) + c4) + c3)
25+
- Code(Counter(5)) at (prev + 0, 20) to (start + 2, 10)
26+
- Branch { true: Counter(6), false: Expression(3, Sub) } at (prev + 3, 9) to (start + 0, 16)
27+
true = c6
28+
false = ((((c1 + c2) + c4) + c3) - c6)
29+
- Code(Counter(3)) at (prev + 0, 14) to (start + 0, 15)
1730
- Code(Counter(6)) at (prev + 0, 20) to (start + 0, 25)
18-
- Branch { true: Counter(3), false: Expression(0, Sub) } at (prev + 0, 20) to (start + 0, 30)
31+
- Branch { true: Counter(3), false: Expression(4, Sub) } at (prev + 0, 20) to (start + 0, 30)
1932
true = c3
2033
false = (c6 - c3)
2134
- Code(Counter(3)) at (prev + 0, 29) to (start + 2, 10)
22-
- Code(Counter(4)) at (prev + 3, 14) to (start + 0, 15)
35+
- Branch { true: Counter(7), false: Expression(5, Sub) } at (prev + 3, 9) to (start + 0, 16)
36+
true = c7
37+
false = (((c1 + c2) + c4) - c7)
38+
- Code(Counter(4)) at (prev + 0, 14) to (start + 0, 15)
2339
- Code(Counter(7)) at (prev + 0, 20) to (start + 0, 25)
2440
- Branch { true: Counter(4), false: Counter(2) } at (prev + 0, 20) to (start + 0, 30)
2541
true = c4
2642
false = c2
2743
- Code(Counter(4)) at (prev + 0, 29) to (start + 2, 10)
28-
- Code(Expression(5, Add)) at (prev + 3, 14) to (start + 2, 10)
44+
- Code(Expression(12, Add)) at (prev + 3, 14) to (start + 2, 10)
2945
= (c1 + c2)
30-
- Code(Expression(2, Add)) at (prev + 4, 1) to (start + 0, 2)
46+
- Code(Expression(9, Add)) at (prev + 4, 1) to (start + 0, 2)
3147
= ((((c1 + c2) + c3) + c4) + c5)
3248

tests/coverage/branch/guard.coverage

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,22 @@
1414
LL| |
1515
LL| 1| match x {
1616
LL| 1| Some(0) => {
17+
------------------
18+
| Branch (LL:9): [True: 1, False: 3]
19+
------------------
1720
LL| 1| println!("zero");
1821
LL| 1| }
1922
LL| 3| Some(x) if x % 2 == 0 => {
2023
^2
2124
------------------
25+
| Branch (LL:9): [True: 3, False: 0]
2226
| Branch (LL:20): [True: 2, False: 1]
2327
------------------
2428
LL| 2| println!("is nonzero and even");
2529
LL| 2| }
2630
LL| 1| Some(x) if x % 3 == 0 => {
2731
------------------
32+
| Branch (LL:9): [True: 1, False: 0]
2833
| Branch (LL:20): [True: 1, False: 0]
2934
------------------
3035
LL| 1| println!("is nonzero and odd, but divisible by 3");

0 commit comments

Comments
 (0)