Skip to content

Commit

Permalink
coverage: Treat each match arm as a "branch" for branch coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
Zalathar committed Apr 19, 2024
1 parent 6d38726 commit 3f670c6
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 46 deletions.
37 changes: 37 additions & 0 deletions compiler/rustc_mir_build/src/build/coverageinfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use rustc_middle::mir::{self, BasicBlock, SourceInfo, SourceScope, UnOp};
use rustc_middle::thir::{ExprId, ExprKind, Thir};
use rustc_middle::ty::TyCtxt;
use rustc_span::def_id::LocalDefId;
use rustc_span::Span;

use crate::build::{Builder, CFG};

Expand Down Expand Up @@ -112,6 +113,31 @@ impl BranchInfoBuilder {
]);
}

fn visit_coverage_match_expr(
&mut self,
cfg: &mut CFG<'_>,
scope: SourceScope,
arms: impl Iterator<Item = (Span, Option<BasicBlock>)>,
) {
let Some(arms) = arms
.map(|(span, pre_binding_block)| Some((span, pre_binding_block?)))
.collect::<Option<Vec<_>>>()
else {
return;
};

let match_arms = arms
.into_iter()
.map(|(span, block)| {
let source_info = SourceInfo { span, scope };
let marker = self.inject_block_marker(cfg, source_info, block);
BranchArm { span, marker }
})
.collect::<Vec<_>>();

self.branch_arm_lists.push(match_arms);
}

fn next_block_marker_id(&mut self) -> BlockMarkerId {
let id = BlockMarkerId::from_usize(self.num_block_markers);
self.num_block_markers += 1;
Expand Down Expand Up @@ -168,4 +194,15 @@ impl Builder<'_, '_> {
else_block,
);
}

/// If branch coverage is enabled, inject marker statements into the given
/// match-arm blocks, and record their IDs in the table of branch arm lists.
pub(crate) fn visit_coverage_match_expr(
&mut self,
arms: impl Iterator<Item = (Span, Option<BasicBlock>)>,
) {
let Some(branch_info) = self.coverage_branch_info.as_mut() else { return };

branch_info.visit_coverage_match_expr(&mut self.cfg, self.source_scope, arms);
}
}
4 changes: 4 additions & 0 deletions compiler/rustc_mir_build/src/build/matches/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
&mut candidates,
);

self.visit_coverage_match_expr(
candidates.iter().map(|c| (c.extra_data.span, c.pre_binding_block)),
);

self.lower_match_arms(
destination,
scrutinee_place,
Expand Down
45 changes: 30 additions & 15 deletions tests/coverage/branch/guard.cov-map
Original file line number Diff line number Diff line change
@@ -1,32 +1,47 @@
Function name: guard::branch_match_guard
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]
Raw bytes (118): 0x[01, 01, 0c, 19, 0f, 1d, 2f, 05, 09, 1d, 2f, 05, 09, 19, 0d, 05, 09, 05, 09, 27, 15, 2b, 11, 2f, 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, 0f, 03, 09, 00, 10, 0d, 00, 0e, 00, 0f, 19, 00, 14, 00, 19, 20, 0d, 16, 00, 14, 00, 1e, 0d, 00, 1d, 02, 0a, 20, 1d, 2f, 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, 2f, 03, 0e, 02, 0a, 23, 04, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 6
- expression 0 operands: lhs = Counter(6), rhs = Counter(3)
- expression 1 operands: lhs = Counter(1), rhs = Counter(2)
- expression 2 operands: lhs = Expression(3, Add), rhs = Counter(5)
- expression 3 operands: lhs = Expression(4, Add), rhs = Counter(4)
- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(3)
- expression 5 operands: lhs = Counter(1), rhs = Counter(2)
Number of file 0 mappings: 13
Number of expressions: 12
- expression 0 operands: lhs = Counter(6), rhs = Expression(3, Add)
- expression 1 operands: lhs = Counter(7), rhs = Expression(11, Add)
- expression 2 operands: lhs = Counter(1), rhs = Counter(2)
- expression 3 operands: lhs = Counter(7), rhs = Expression(11, Add)
- expression 4 operands: lhs = Counter(1), rhs = Counter(2)
- expression 5 operands: lhs = Counter(6), rhs = Counter(3)
- expression 6 operands: lhs = Counter(1), rhs = Counter(2)
- expression 7 operands: lhs = Counter(1), rhs = Counter(2)
- expression 8 operands: lhs = Expression(9, Add), rhs = Counter(5)
- expression 9 operands: lhs = Expression(10, Add), rhs = Counter(4)
- expression 10 operands: lhs = Expression(11, Add), rhs = Counter(3)
- expression 11 operands: lhs = Counter(1), rhs = Counter(2)
Number of file 0 mappings: 16
- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16)
- Code(Counter(7)) at (prev + 3, 11) to (start + 0, 12)
- Code(Counter(5)) at (prev + 1, 20) to (start + 2, 10)
- Code(Counter(3)) at (prev + 3, 14) to (start + 0, 15)
- Branch { true: Counter(5), false: Expression(0, Add) } at (prev + 1, 9) to (start + 0, 16)
true = c5
false = (c6 + (c7 + (c1 + c2)))
- Code(Counter(5)) at (prev + 0, 20) to (start + 2, 10)
- Branch { true: Counter(6), false: Expression(3, Add) } at (prev + 3, 9) to (start + 0, 16)
true = c6
false = (c7 + (c1 + c2))
- Code(Counter(3)) at (prev + 0, 14) to (start + 0, 15)
- Code(Counter(6)) at (prev + 0, 20) to (start + 0, 25)
- Branch { true: Counter(3), false: Expression(0, Sub) } at (prev + 0, 20) to (start + 0, 30)
- Branch { true: Counter(3), false: Expression(5, Sub) } at (prev + 0, 20) to (start + 0, 30)
true = c3
false = (c6 - c3)
- Code(Counter(3)) at (prev + 0, 29) to (start + 2, 10)
- Code(Counter(4)) at (prev + 3, 14) to (start + 0, 15)
- Branch { true: Counter(7), false: Expression(11, Add) } at (prev + 3, 9) to (start + 0, 16)
true = c7
false = (c1 + c2)
- Code(Counter(4)) at (prev + 0, 14) to (start + 0, 15)
- Code(Counter(7)) at (prev + 0, 20) to (start + 0, 25)
- Branch { true: Counter(4), false: Counter(2) } at (prev + 0, 20) to (start + 0, 30)
true = c4
false = c2
- Code(Counter(4)) at (prev + 0, 29) to (start + 2, 10)
- Code(Expression(5, Add)) at (prev + 3, 14) to (start + 2, 10)
- Code(Expression(11, Add)) at (prev + 3, 14) to (start + 2, 10)
= (c1 + c2)
- Code(Expression(2, Add)) at (prev + 4, 1) to (start + 0, 2)
- Code(Expression(8, Add)) at (prev + 4, 1) to (start + 0, 2)
= ((((c1 + c2) + c3) + c4) + c5)

5 changes: 5 additions & 0 deletions tests/coverage/branch/guard.coverage
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,22 @@
LL| |
LL| 1| match x {
LL| 1| Some(0) => {
------------------
| Branch (LL:9): [True: 1, False: 4]
------------------
LL| 1| println!("zero");
LL| 1| }
LL| 3| Some(x) if x % 2 == 0 => {
^2
------------------
| Branch (LL:9): [True: 3, False: 1]
| Branch (LL:20): [True: 2, False: 1]
------------------
LL| 2| println!("is nonzero and even");
LL| 2| }
LL| 1| Some(x) if x % 3 == 0 => {
------------------
| Branch (LL:9): [True: 1, False: 0]
| Branch (LL:20): [True: 1, False: 0]
------------------
LL| 1| println!("is nonzero and odd, but divisible by 3");
Expand Down
124 changes: 93 additions & 31 deletions tests/coverage/branch/match-arms.cov-map
Original file line number Diff line number Diff line change
@@ -1,60 +1,122 @@
Function name: match_arms::guards
Raw bytes (88): 0x[01, 01, 08, 07, 15, 0b, 11, 0f, 0d, 00, 09, 17, 25, 1b, 21, 1f, 1d, 03, 19, 0c, 01, 31, 01, 01, 10, 29, 03, 0b, 00, 10, 19, 01, 11, 00, 29, 20, 19, 09, 00, 17, 00, 1b, 1d, 01, 11, 00, 29, 20, 1d, 0d, 00, 17, 00, 1b, 21, 01, 11, 00, 29, 20, 21, 11, 00, 17, 00, 1b, 25, 01, 11, 00, 29, 20, 25, 15, 00, 17, 00, 1b, 03, 01, 0e, 00, 18, 13, 03, 05, 01, 02]
Raw bytes (180): 0x[01, 01, 22, 31, 1f, 2d, 37, 29, 7b, 7f, 15, 83, 01, 11, 87, 01, 0d, 00, 09, 2d, 37, 29, 7b, 7f, 15, 83, 01, 11, 87, 01, 0d, 00, 09, 29, 7b, 7f, 15, 83, 01, 11, 87, 01, 0d, 00, 09, 7f, 15, 83, 01, 11, 87, 01, 0d, 00, 09, 7f, 15, 83, 01, 11, 87, 01, 0d, 00, 09, 6f, 25, 73, 21, 77, 1d, 7b, 19, 7f, 15, 83, 01, 11, 87, 01, 0d, 00, 09, 10, 01, 31, 01, 01, 10, 29, 03, 0b, 00, 10, 20, 35, 03, 01, 09, 00, 13, 19, 00, 11, 00, 29, 20, 19, 09, 00, 17, 00, 1b, 20, 31, 1f, 01, 09, 00, 13, 1d, 00, 11, 00, 29, 20, 1d, 0d, 00, 17, 00, 1b, 20, 2d, 37, 01, 09, 00, 13, 21, 00, 11, 00, 29, 20, 21, 11, 00, 17, 00, 1b, 20, 29, 7b, 01, 09, 00, 13, 25, 00, 11, 00, 29, 20, 25, 15, 00, 17, 00, 1b, 7b, 01, 0e, 00, 18, 6b, 03, 05, 01, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 8
- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(5)
- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(4)
- expression 2 operands: lhs = Expression(3, Add), rhs = Counter(3)
- expression 3 operands: lhs = Zero, rhs = Counter(2)
- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(9)
- expression 5 operands: lhs = Expression(6, Add), rhs = Counter(8)
- expression 6 operands: lhs = Expression(7, Add), rhs = Counter(7)
- expression 7 operands: lhs = Expression(0, Add), rhs = Counter(6)
Number of file 0 mappings: 12
Number of expressions: 34
- expression 0 operands: lhs = Counter(12), rhs = Expression(7, Add)
- expression 1 operands: lhs = Counter(11), rhs = Expression(13, Add)
- expression 2 operands: lhs = Counter(10), rhs = Expression(30, Add)
- expression 3 operands: lhs = Expression(31, Add), rhs = Counter(5)
- expression 4 operands: lhs = Expression(32, Add), rhs = Counter(4)
- expression 5 operands: lhs = Expression(33, Add), rhs = Counter(3)
- expression 6 operands: lhs = Zero, rhs = Counter(2)
- expression 7 operands: lhs = Counter(11), rhs = Expression(13, Add)
- expression 8 operands: lhs = Counter(10), rhs = Expression(30, Add)
- expression 9 operands: lhs = Expression(31, Add), rhs = Counter(5)
- expression 10 operands: lhs = Expression(32, Add), rhs = Counter(4)
- expression 11 operands: lhs = Expression(33, Add), rhs = Counter(3)
- expression 12 operands: lhs = Zero, rhs = Counter(2)
- expression 13 operands: lhs = Counter(10), rhs = Expression(30, Add)
- expression 14 operands: lhs = Expression(31, Add), rhs = Counter(5)
- expression 15 operands: lhs = Expression(32, Add), rhs = Counter(4)
- expression 16 operands: lhs = Expression(33, Add), rhs = Counter(3)
- expression 17 operands: lhs = Zero, rhs = Counter(2)
- expression 18 operands: lhs = Expression(31, Add), rhs = Counter(5)
- expression 19 operands: lhs = Expression(32, Add), rhs = Counter(4)
- expression 20 operands: lhs = Expression(33, Add), rhs = Counter(3)
- expression 21 operands: lhs = Zero, rhs = Counter(2)
- expression 22 operands: lhs = Expression(31, Add), rhs = Counter(5)
- expression 23 operands: lhs = Expression(32, Add), rhs = Counter(4)
- expression 24 operands: lhs = Expression(33, Add), rhs = Counter(3)
- expression 25 operands: lhs = Zero, rhs = Counter(2)
- expression 26 operands: lhs = Expression(27, Add), rhs = Counter(9)
- expression 27 operands: lhs = Expression(28, Add), rhs = Counter(8)
- expression 28 operands: lhs = Expression(29, Add), rhs = Counter(7)
- expression 29 operands: lhs = Expression(30, Add), rhs = Counter(6)
- expression 30 operands: lhs = Expression(31, Add), rhs = Counter(5)
- expression 31 operands: lhs = Expression(32, Add), rhs = Counter(4)
- expression 32 operands: lhs = Expression(33, Add), rhs = Counter(3)
- expression 33 operands: lhs = Zero, rhs = Counter(2)
Number of file 0 mappings: 16
- Code(Counter(0)) at (prev + 49, 1) to (start + 1, 16)
- Code(Counter(10)) at (prev + 3, 11) to (start + 0, 16)
- Code(Counter(6)) at (prev + 1, 17) to (start + 0, 41)
- Branch { true: Counter(13), false: Expression(0, Add) } at (prev + 1, 9) to (start + 0, 19)
true = c13
false = (c12 + (c11 + (c10 + ((((Zero + c2) + c3) + c4) + c5))))
- Code(Counter(6)) at (prev + 0, 17) to (start + 0, 41)
- Branch { true: Counter(6), false: Counter(2) } at (prev + 0, 23) to (start + 0, 27)
true = c6
false = c2
- Code(Counter(7)) at (prev + 1, 17) to (start + 0, 41)
- Branch { true: Counter(12), false: Expression(7, Add) } at (prev + 1, 9) to (start + 0, 19)
true = c12
false = (c11 + (c10 + ((((Zero + c2) + c3) + c4) + c5)))
- Code(Counter(7)) at (prev + 0, 17) to (start + 0, 41)
- Branch { true: Counter(7), false: Counter(3) } at (prev + 0, 23) to (start + 0, 27)
true = c7
false = c3
- Code(Counter(8)) at (prev + 1, 17) to (start + 0, 41)
- Branch { true: Counter(11), false: Expression(13, Add) } at (prev + 1, 9) to (start + 0, 19)
true = c11
false = (c10 + ((((Zero + c2) + c3) + c4) + c5))
- Code(Counter(8)) at (prev + 0, 17) to (start + 0, 41)
- Branch { true: Counter(8), false: Counter(4) } at (prev + 0, 23) to (start + 0, 27)
true = c8
false = c4
- Code(Counter(9)) at (prev + 1, 17) to (start + 0, 41)
- Branch { true: Counter(10), false: Expression(30, Add) } at (prev + 1, 9) to (start + 0, 19)
true = c10
false = ((((Zero + c2) + c3) + c4) + c5)
- Code(Counter(9)) at (prev + 0, 17) to (start + 0, 41)
- Branch { true: Counter(9), false: Counter(5) } at (prev + 0, 23) to (start + 0, 27)
true = c9
false = c5
- Code(Expression(0, Add)) at (prev + 1, 14) to (start + 0, 24)
- Code(Expression(30, Add)) at (prev + 1, 14) to (start + 0, 24)
= ((((Zero + c2) + c3) + c4) + c5)
- Code(Expression(4, Add)) at (prev + 3, 5) to (start + 1, 2)
- Code(Expression(26, Add)) at (prev + 3, 5) to (start + 1, 2)
= ((((((((Zero + c2) + c3) + c4) + c5) + c6) + c7) + c8) + c9)

Function name: match_arms::match_arms
Raw bytes (51): 0x[01, 01, 06, 05, 07, 0b, 11, 09, 0d, 13, 02, 17, 09, 11, 0d, 07, 01, 19, 01, 01, 10, 05, 03, 0b, 00, 10, 11, 01, 11, 00, 21, 0d, 01, 11, 00, 21, 09, 01, 11, 00, 21, 02, 01, 11, 00, 21, 0f, 03, 05, 01, 02]
Raw bytes (102): 0x[01, 01, 15, 0d, 17, 09, 4a, 05, 4f, 53, 11, 09, 0d, 09, 4a, 05, 4f, 53, 11, 09, 0d, 05, 4f, 53, 11, 09, 0d, 05, 4f, 53, 11, 09, 0d, 43, 4a, 47, 09, 11, 0d, 05, 4f, 53, 11, 09, 0d, 0a, 01, 19, 01, 01, 10, 05, 03, 0b, 00, 10, 20, 11, 03, 01, 09, 00, 13, 11, 00, 11, 00, 21, 20, 0d, 17, 01, 09, 00, 13, 0d, 00, 11, 00, 21, 20, 09, 4a, 01, 09, 00, 13, 09, 00, 11, 00, 21, 4a, 01, 11, 00, 21, 3f, 03, 05, 01, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 6
- expression 0 operands: lhs = Counter(1), rhs = Expression(1, Add)
- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(4)
- expression 2 operands: lhs = Counter(2), rhs = Counter(3)
- expression 3 operands: lhs = Expression(4, Add), rhs = Expression(0, Sub)
- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(2)
- expression 5 operands: lhs = Counter(4), rhs = Counter(3)
Number of file 0 mappings: 7
Number of expressions: 21
- expression 0 operands: lhs = Counter(3), rhs = Expression(5, Add)
- expression 1 operands: lhs = Counter(2), rhs = Expression(18, Sub)
- expression 2 operands: lhs = Counter(1), rhs = Expression(19, Add)
- expression 3 operands: lhs = Expression(20, Add), rhs = Counter(4)
- expression 4 operands: lhs = Counter(2), rhs = Counter(3)
- expression 5 operands: lhs = Counter(2), rhs = Expression(18, Sub)
- expression 6 operands: lhs = Counter(1), rhs = Expression(19, Add)
- expression 7 operands: lhs = Expression(20, Add), rhs = Counter(4)
- expression 8 operands: lhs = Counter(2), rhs = Counter(3)
- expression 9 operands: lhs = Counter(1), rhs = Expression(19, Add)
- expression 10 operands: lhs = Expression(20, Add), rhs = Counter(4)
- expression 11 operands: lhs = Counter(2), rhs = Counter(3)
- expression 12 operands: lhs = Counter(1), rhs = Expression(19, Add)
- expression 13 operands: lhs = Expression(20, Add), rhs = Counter(4)
- expression 14 operands: lhs = Counter(2), rhs = Counter(3)
- expression 15 operands: lhs = Expression(16, Add), rhs = Expression(18, Sub)
- expression 16 operands: lhs = Expression(17, Add), rhs = Counter(2)
- expression 17 operands: lhs = Counter(4), rhs = Counter(3)
- expression 18 operands: lhs = Counter(1), rhs = Expression(19, Add)
- expression 19 operands: lhs = Expression(20, Add), rhs = Counter(4)
- expression 20 operands: lhs = Counter(2), rhs = Counter(3)
Number of file 0 mappings: 10
- Code(Counter(0)) at (prev + 25, 1) to (start + 1, 16)
- Code(Counter(1)) at (prev + 3, 11) to (start + 0, 16)
- Code(Counter(4)) at (prev + 1, 17) to (start + 0, 33)
- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 33)
- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 33)
- Code(Expression(0, Sub)) at (prev + 1, 17) to (start + 0, 33)
- Branch { true: Counter(4), false: Expression(0, Add) } at (prev + 1, 9) to (start + 0, 19)
true = c4
false = (c3 + (c2 + (c1 - ((c2 + c3) + c4))))
- Code(Counter(4)) at (prev + 0, 17) to (start + 0, 33)
- Branch { true: Counter(3), false: Expression(5, Add) } at (prev + 1, 9) to (start + 0, 19)
true = c3
false = (c2 + (c1 - ((c2 + c3) + c4)))
- Code(Counter(3)) at (prev + 0, 17) to (start + 0, 33)
- Branch { true: Counter(2), false: Expression(18, Sub) } at (prev + 1, 9) to (start + 0, 19)
true = c2
false = (c1 - ((c2 + c3) + c4))
- Code(Counter(2)) at (prev + 0, 17) to (start + 0, 33)
- Code(Expression(18, Sub)) at (prev + 1, 17) to (start + 0, 33)
= (c1 - ((c2 + c3) + c4))
- Code(Expression(3, Add)) at (prev + 3, 5) to (start + 1, 2)
- Code(Expression(15, Add)) at (prev + 3, 5) to (start + 1, 2)
= (((c4 + c3) + c2) + (c1 - ((c2 + c3) + c4)))

Function name: match_arms::or_patterns
Expand Down
13 changes: 13 additions & 0 deletions tests/coverage/branch/match-arms.coverage
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,17 @@
LL| |
LL| 15| match value {
LL| 8| Enum::D(d) => consume(d),
------------------
| Branch (LL:9): [True: 8, False: 7]
------------------
LL| 4| Enum::C(c) => consume(c),
------------------
| Branch (LL:9): [True: 4, False: 3]
------------------
LL| 2| Enum::B(b) => consume(b),
------------------
| Branch (LL:9): [True: 2, False: 1]
------------------
LL| 1| Enum::A(a) => consume(a),
LL| | }
LL| |
Expand All @@ -54,18 +63,22 @@
LL| 3| match value {
LL| 8| Enum::D(d) if cond => consume(d),
------------------
| Branch (LL:9): [True: 24, False: 51]
| Branch (LL:23): [True: 8, False: 16]
------------------
LL| 4| Enum::C(c) if cond => consume(c),
------------------
| Branch (LL:9): [True: 12, False: 39]
| Branch (LL:23): [True: 4, False: 8]
------------------
LL| 2| Enum::B(b) if cond => consume(b),
------------------
| Branch (LL:9): [True: 6, False: 33]
| Branch (LL:23): [True: 2, False: 4]
------------------
LL| 1| Enum::A(a) if cond => consume(a),
------------------
| Branch (LL:9): [True: 3, False: 30]
| Branch (LL:23): [True: 1, False: 2]
------------------
LL| 30| _ => consume(0),
Expand Down

0 comments on commit 3f670c6

Please sign in to comment.