Skip to content

Commit 9c9b568

Browse files
committed
Auto merge of rust-lang#124603 - Zalathar:mcdc-mappings, r=Nadrieril
coverage: Split out MC/DC mappings from `BcbMappingKind` These variants were added to `BcbMappingKind` as part of the [MC/DC coverage](https://en.wikipedia.org/wiki/Modified_Condition/Decision_Coverage) implementation in rust-lang#123409, because that was the path-of-least-resistance for integrating them into the existing code. However, they ultimately represent complex concepts that the enum was not intended to handle, leading to more complexity in the code that processes them. This PR therefore follows in the footsteps of rust-lang#124545, and splits the MC/DC mappings out into their own dedicated vectors of structs. After that, `BcbMappingKind` itself ends up having only one variant (`Code`), so this PR also flattens that enum into its enclosing struct, renamed to `mapping::CodeMapping`. --- No functional changes. This will conflict slightly with rust-lang#124571, but hopefully that should be easy to resolve either way. `@rustbot` label +A-code-coverage
2 parents 872a856 + 6968123 commit 9c9b568

File tree

3 files changed

+158
-157
lines changed

3 files changed

+158
-157
lines changed

compiler/rustc_mir_transform/src/coverage/mappings.rs

+109-104
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@ use std::collections::BTreeSet;
22

33
use rustc_data_structures::graph::DirectedGraph;
44
use rustc_index::bit_set::BitSet;
5-
use rustc_middle::mir::coverage::{
6-
BlockMarkerId, BranchSpan, ConditionInfo, CoverageKind, MCDCBranchSpan, MCDCDecisionSpan,
7-
};
5+
use rustc_index::IndexVec;
6+
use rustc_middle::mir::coverage::{BlockMarkerId, BranchSpan, ConditionInfo, CoverageKind};
87
use rustc_middle::mir::{self, BasicBlock, StatementKind};
98
use rustc_span::Span;
109

@@ -13,55 +12,53 @@ use crate::coverage::spans::{
1312
extract_refined_covspans, unexpand_into_body_span_with_visible_macro,
1413
};
1514
use crate::coverage::ExtractedHirInfo;
16-
use rustc_index::IndexVec;
17-
18-
#[derive(Clone, Debug)]
19-
pub(super) enum BcbMappingKind {
20-
/// Associates an ordinary executable code span with its corresponding BCB.
21-
Code(BasicCoverageBlock),
22-
23-
// Ordinary branch mappings are stored separately, so they don't have a
24-
// variant in this enum.
25-
//
26-
/// Associates a mcdc branch span with condition info besides fields for normal branch.
27-
MCDCBranch {
28-
true_bcb: BasicCoverageBlock,
29-
false_bcb: BasicCoverageBlock,
30-
/// If `None`, this actually represents a normal branch mapping inserted
31-
/// for code that was too complex for MC/DC.
32-
condition_info: Option<ConditionInfo>,
33-
decision_depth: u16,
34-
},
35-
/// Associates a mcdc decision with its join BCB.
36-
MCDCDecision {
37-
end_bcbs: BTreeSet<BasicCoverageBlock>,
38-
bitmap_idx: u32,
39-
conditions_num: u16,
40-
decision_depth: u16,
41-
},
42-
}
4315

16+
/// Associates an ordinary executable code span with its corresponding BCB.
4417
#[derive(Debug)]
45-
pub(super) struct BcbMapping {
46-
pub(super) kind: BcbMappingKind,
18+
pub(super) struct CodeMapping {
4719
pub(super) span: Span,
20+
pub(super) bcb: BasicCoverageBlock,
4821
}
4922

50-
/// This is separate from [`BcbMappingKind`] to help prepare for larger changes
23+
/// This is separate from [`MCDCBranch`] to help prepare for larger changes
5124
/// that will be needed for improved branch coverage in the future.
5225
/// (See <https://github.com/rust-lang/rust/pull/124217>.)
5326
#[derive(Debug)]
54-
pub(super) struct BcbBranchPair {
27+
pub(super) struct BranchPair {
5528
pub(super) span: Span,
5629
pub(super) true_bcb: BasicCoverageBlock,
5730
pub(super) false_bcb: BasicCoverageBlock,
5831
}
5932

33+
/// Associates an MC/DC branch span with condition info besides fields for normal branch.
34+
#[derive(Debug)]
35+
pub(super) struct MCDCBranch {
36+
pub(super) span: Span,
37+
pub(super) true_bcb: BasicCoverageBlock,
38+
pub(super) false_bcb: BasicCoverageBlock,
39+
/// If `None`, this actually represents a normal branch mapping inserted
40+
/// for code that was too complex for MC/DC.
41+
pub(super) condition_info: Option<ConditionInfo>,
42+
pub(super) decision_depth: u16,
43+
}
44+
45+
/// Associates an MC/DC decision with its join BCBs.
46+
#[derive(Debug)]
47+
pub(super) struct MCDCDecision {
48+
pub(super) span: Span,
49+
pub(super) end_bcbs: BTreeSet<BasicCoverageBlock>,
50+
pub(super) bitmap_idx: u32,
51+
pub(super) conditions_num: u16,
52+
pub(super) decision_depth: u16,
53+
}
54+
6055
pub(super) struct CoverageSpans {
6156
bcb_has_mappings: BitSet<BasicCoverageBlock>,
62-
pub(super) mappings: Vec<BcbMapping>,
63-
pub(super) branch_pairs: Vec<BcbBranchPair>,
57+
pub(super) code_mappings: Vec<CodeMapping>,
58+
pub(super) branch_pairs: Vec<BranchPair>,
6459
test_vector_bitmap_bytes: u32,
60+
pub(super) mcdc_branches: Vec<MCDCBranch>,
61+
pub(super) mcdc_decisions: Vec<MCDCDecision>,
6562
}
6663

6764
impl CoverageSpans {
@@ -83,26 +80,38 @@ pub(super) fn generate_coverage_spans(
8380
hir_info: &ExtractedHirInfo,
8481
basic_coverage_blocks: &CoverageGraph,
8582
) -> Option<CoverageSpans> {
86-
let mut mappings = vec![];
83+
let mut code_mappings = vec![];
8784
let mut branch_pairs = vec![];
85+
let mut mcdc_branches = vec![];
86+
let mut mcdc_decisions = vec![];
8887

8988
if hir_info.is_async_fn {
9089
// An async function desugars into a function that returns a future,
9190
// with the user code wrapped in a closure. Any spans in the desugared
9291
// outer function will be unhelpful, so just keep the signature span
9392
// and ignore all of the spans in the MIR body.
9493
if let Some(span) = hir_info.fn_sig_span_extended {
95-
mappings.push(BcbMapping { kind: BcbMappingKind::Code(START_BCB), span });
94+
code_mappings.push(CodeMapping { span, bcb: START_BCB });
9695
}
9796
} else {
98-
extract_refined_covspans(mir_body, hir_info, basic_coverage_blocks, &mut mappings);
97+
extract_refined_covspans(mir_body, hir_info, basic_coverage_blocks, &mut code_mappings);
9998

10099
branch_pairs.extend(extract_branch_pairs(mir_body, hir_info, basic_coverage_blocks));
101100

102-
mappings.extend(extract_mcdc_mappings(mir_body, hir_info.body_span, basic_coverage_blocks));
101+
extract_mcdc_mappings(
102+
mir_body,
103+
hir_info.body_span,
104+
basic_coverage_blocks,
105+
&mut mcdc_branches,
106+
&mut mcdc_decisions,
107+
);
103108
}
104109

105-
if mappings.is_empty() && branch_pairs.is_empty() {
110+
if code_mappings.is_empty()
111+
&& branch_pairs.is_empty()
112+
&& mcdc_branches.is_empty()
113+
&& mcdc_decisions.is_empty()
114+
{
106115
return None;
107116
}
108117

@@ -111,29 +120,36 @@ pub(super) fn generate_coverage_spans(
111120
let mut insert = |bcb| {
112121
bcb_has_mappings.insert(bcb);
113122
};
114-
let mut test_vector_bitmap_bytes = 0;
115-
for BcbMapping { kind, span: _ } in &mappings {
116-
match *kind {
117-
BcbMappingKind::Code(bcb) => insert(bcb),
118-
BcbMappingKind::MCDCBranch { true_bcb, false_bcb, .. } => {
119-
insert(true_bcb);
120-
insert(false_bcb);
121-
}
122-
BcbMappingKind::MCDCDecision { bitmap_idx, conditions_num, .. } => {
123-
// `bcb_has_mappings` is used for inject coverage counters
124-
// but they are not needed for decision BCBs.
125-
// While the length of test vector bitmap should be calculated here.
126-
test_vector_bitmap_bytes = test_vector_bitmap_bytes
127-
.max(bitmap_idx + (1_u32 << conditions_num as u32).div_ceil(8));
128-
}
129-
}
123+
124+
for &CodeMapping { span: _, bcb } in &code_mappings {
125+
insert(bcb);
126+
}
127+
for &BranchPair { true_bcb, false_bcb, .. } in &branch_pairs {
128+
insert(true_bcb);
129+
insert(false_bcb);
130130
}
131-
for &BcbBranchPair { true_bcb, false_bcb, .. } in &branch_pairs {
131+
for &MCDCBranch { true_bcb, false_bcb, .. } in &mcdc_branches {
132132
insert(true_bcb);
133133
insert(false_bcb);
134134
}
135135

136-
Some(CoverageSpans { bcb_has_mappings, mappings, branch_pairs, test_vector_bitmap_bytes })
136+
// Determine the length of the test vector bitmap.
137+
let test_vector_bitmap_bytes = mcdc_decisions
138+
.iter()
139+
.map(|&MCDCDecision { bitmap_idx, conditions_num, .. }| {
140+
bitmap_idx + (1_u32 << u32::from(conditions_num)).div_ceil(8)
141+
})
142+
.max()
143+
.unwrap_or(0);
144+
145+
Some(CoverageSpans {
146+
bcb_has_mappings,
147+
code_mappings,
148+
branch_pairs,
149+
test_vector_bitmap_bytes,
150+
mcdc_branches,
151+
mcdc_decisions,
152+
})
137153
}
138154

139155
fn resolve_block_markers(
@@ -167,7 +183,7 @@ pub(super) fn extract_branch_pairs(
167183
mir_body: &mir::Body<'_>,
168184
hir_info: &ExtractedHirInfo,
169185
basic_coverage_blocks: &CoverageGraph,
170-
) -> Vec<BcbBranchPair> {
186+
) -> Vec<BranchPair> {
171187
let Some(branch_info) = mir_body.coverage_branch_info.as_deref() else { return vec![] };
172188

173189
let block_markers = resolve_block_markers(branch_info, mir_body);
@@ -190,7 +206,7 @@ pub(super) fn extract_branch_pairs(
190206
let true_bcb = bcb_from_marker(true_marker)?;
191207
let false_bcb = bcb_from_marker(false_marker)?;
192208

193-
Some(BcbBranchPair { span, true_bcb, false_bcb })
209+
Some(BranchPair { span, true_bcb, false_bcb })
194210
})
195211
.collect::<Vec<_>>()
196212
}
@@ -199,10 +215,10 @@ pub(super) fn extract_mcdc_mappings(
199215
mir_body: &mir::Body<'_>,
200216
body_span: Span,
201217
basic_coverage_blocks: &CoverageGraph,
202-
) -> Vec<BcbMapping> {
203-
let Some(branch_info) = mir_body.coverage_branch_info.as_deref() else {
204-
return vec![];
205-
};
218+
mcdc_branches: &mut impl Extend<MCDCBranch>,
219+
mcdc_decisions: &mut impl Extend<MCDCDecision>,
220+
) {
221+
let Some(branch_info) = mir_body.coverage_branch_info.as_deref() else { return };
206222

207223
let block_markers = resolve_block_markers(branch_info, mir_body);
208224

@@ -223,53 +239,42 @@ pub(super) fn extract_mcdc_mappings(
223239
Some((span, true_bcb, false_bcb))
224240
};
225241

226-
let mcdc_branch_filter_map = |&MCDCBranchSpan {
227-
span: raw_span,
228-
true_marker,
229-
false_marker,
230-
condition_info,
231-
decision_depth,
232-
}| {
233-
check_branch_bcb(raw_span, true_marker, false_marker).map(|(span, true_bcb, false_bcb)| {
234-
BcbMapping {
235-
kind: BcbMappingKind::MCDCBranch {
236-
true_bcb,
237-
false_bcb,
238-
condition_info,
239-
decision_depth,
240-
},
241-
span,
242-
}
243-
})
244-
};
242+
mcdc_branches.extend(branch_info.mcdc_branch_spans.iter().filter_map(
243+
|&mir::coverage::MCDCBranchSpan {
244+
span: raw_span,
245+
condition_info,
246+
true_marker,
247+
false_marker,
248+
decision_depth,
249+
}| {
250+
let (span, true_bcb, false_bcb) =
251+
check_branch_bcb(raw_span, true_marker, false_marker)?;
252+
Some(MCDCBranch { span, true_bcb, false_bcb, condition_info, decision_depth })
253+
},
254+
));
245255

246256
let mut next_bitmap_idx = 0;
247257

248-
let decision_filter_map = |decision: &MCDCDecisionSpan| {
249-
let (span, _) = unexpand_into_body_span_with_visible_macro(decision.span, body_span)?;
258+
mcdc_decisions.extend(branch_info.mcdc_decision_spans.iter().filter_map(
259+
|decision: &mir::coverage::MCDCDecisionSpan| {
260+
let (span, _) = unexpand_into_body_span_with_visible_macro(decision.span, body_span)?;
250261

251-
let end_bcbs = decision
252-
.end_markers
253-
.iter()
254-
.map(|&marker| bcb_from_marker(marker))
255-
.collect::<Option<_>>()?;
262+
let end_bcbs = decision
263+
.end_markers
264+
.iter()
265+
.map(|&marker| bcb_from_marker(marker))
266+
.collect::<Option<_>>()?;
256267

257-
let bitmap_idx = next_bitmap_idx;
258-
next_bitmap_idx += (1_u32 << decision.conditions_num).div_ceil(8);
268+
let bitmap_idx = next_bitmap_idx;
269+
next_bitmap_idx += (1_u32 << decision.conditions_num).div_ceil(8);
259270

260-
Some(BcbMapping {
261-
kind: BcbMappingKind::MCDCDecision {
271+
Some(MCDCDecision {
272+
span,
262273
end_bcbs,
263274
bitmap_idx,
264275
conditions_num: decision.conditions_num as u16,
265276
decision_depth: decision.decision_depth,
266-
},
267-
span,
268-
})
269-
};
270-
271-
std::iter::empty()
272-
.chain(branch_info.mcdc_branch_spans.iter().filter_map(mcdc_branch_filter_map))
273-
.chain(branch_info.mcdc_decision_spans.iter().filter_map(decision_filter_map))
274-
.collect::<Vec<_>>()
277+
})
278+
},
279+
));
275280
}

0 commit comments

Comments
 (0)