coverage. Generate Mappings of decisions and conditions for MC/DC

This commit is contained in:
zhuyunxing
2024-04-19 10:53:04 +08:00
parent 68f86381ee
commit cf6b6cb2b4
10 changed files with 779 additions and 41 deletions

View File

@@ -1,7 +1,9 @@
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxHashSet;
use rustc_index::IndexVec;
use rustc_middle::mir::coverage::{BlockMarkerId, BranchSpan, CoverageKind};
use rustc_middle::mir::coverage::{
BlockMarkerId, BranchSpan, CoverageKind, MCDCBranchSpan, MCDCDecisionSpan,
};
use rustc_middle::mir::{
self, AggregateKind, BasicBlock, FakeReadCause, Rvalue, Statement, StatementKind, Terminator,
TerminatorKind,
@@ -227,7 +229,10 @@ fn filtered_statement_span(statement: &Statement<'_>) -> Option<Span> {
// These coverage statements should not exist prior to coverage instrumentation.
StatementKind::Coverage(
CoverageKind::CounterIncrement { .. } | CoverageKind::ExpressionUsed { .. },
CoverageKind::CounterIncrement { .. }
| CoverageKind::ExpressionUsed { .. }
| CoverageKind::CondBitmapUpdate { .. }
| CoverageKind::TestVectorBitmapUpdate { .. },
) => bug!(
"Unexpected coverage statement found during coverage instrumentation: {statement:?}"
),
@@ -384,10 +389,11 @@ pub(super) fn extract_branch_mappings(
}
}
branch_info
.branch_spans
.iter()
.filter_map(|&BranchSpan { span: raw_span, true_marker, false_marker }| {
let bcb_from_marker =
|marker: BlockMarkerId| basic_coverage_blocks.bcb_from_bb(block_markers[marker]?);
let check_branch_bcb =
|raw_span: Span, true_marker: BlockMarkerId, false_marker: BlockMarkerId| {
// For now, ignore any branch span that was introduced by
// expansion. This makes things like assert macros less noisy.
if !raw_span.ctxt().outer_expn_data().is_root() {
@@ -395,13 +401,56 @@ pub(super) fn extract_branch_mappings(
}
let (span, _) = unexpand_into_body_span_with_visible_macro(raw_span, body_span)?;
let bcb_from_marker =
|marker: BlockMarkerId| basic_coverage_blocks.bcb_from_bb(block_markers[marker]?);
let true_bcb = bcb_from_marker(true_marker)?;
let false_bcb = bcb_from_marker(false_marker)?;
Some((span, true_bcb, false_bcb))
};
Some(BcbMapping { kind: BcbMappingKind::Branch { true_bcb, false_bcb }, span })
let branch_filter_map = |&BranchSpan { span: raw_span, true_marker, false_marker }| {
check_branch_bcb(raw_span, true_marker, false_marker).map(|(span, true_bcb, false_bcb)| {
BcbMapping { kind: BcbMappingKind::Branch { true_bcb, false_bcb }, span }
})
};
let mcdc_branch_filter_map =
|&MCDCBranchSpan { span: raw_span, true_marker, false_marker, condition_info }| {
check_branch_bcb(raw_span, true_marker, false_marker).map(
|(span, true_bcb, false_bcb)| BcbMapping {
kind: BcbMappingKind::MCDCBranch { true_bcb, false_bcb, condition_info },
span,
},
)
};
let mut next_bitmap_idx = 0;
let decision_filter_map = |decision: &MCDCDecisionSpan| {
let (span, _) = unexpand_into_body_span_with_visible_macro(decision.span, body_span)?;
let end_bcbs = decision
.end_markers
.iter()
.map(|&marker| bcb_from_marker(marker))
.collect::<Option<_>>()?;
let bitmap_idx = next_bitmap_idx;
next_bitmap_idx += (1_u32 << decision.conditions_num).div_ceil(8);
Some(BcbMapping {
kind: BcbMappingKind::MCDCDecision {
end_bcbs,
bitmap_idx,
conditions_num: decision.conditions_num as u16,
},
span,
})
};
branch_info
.branch_spans
.iter()
.filter_map(branch_filter_map)
.chain(branch_info.mcdc_branch_spans.iter().filter_map(mcdc_branch_filter_map))
.chain(branch_info.mcdc_decision_spans.iter().filter_map(decision_filter_map))
.collect::<Vec<_>>()
}