mcdc-coverage: Add decision_depth field in structs

Add decision_depth field to TVBitmapUpdate/CondBitmapUpdate statements
Add decision_depth field to BcbMappingKinds MCDCBranch and MCDCDecision
Add decision_depth field to MCDCBranchSpan and MCDCDecisionSpan
This commit is contained in:
Dorian Péron 2024-04-08 14:44:25 +00:00
parent 3c2f48ede9
commit ae8c023983
7 changed files with 78 additions and 39 deletions

View File

@ -154,7 +154,7 @@ fn add_coverage(&mut self, instance: Instance<'tcx>, kind: &CoverageKind) {
CoverageKind::ExpressionUsed { id } => { CoverageKind::ExpressionUsed { id } => {
func_coverage.mark_expression_id_seen(id); func_coverage.mark_expression_id_seen(id);
} }
CoverageKind::CondBitmapUpdate { id, value, .. } => { CoverageKind::CondBitmapUpdate { id, value, decision_depth } => {
drop(coverage_map); drop(coverage_map);
assert_ne!( assert_ne!(
id.as_u32(), id.as_u32(),
@ -162,7 +162,7 @@ fn add_coverage(&mut self, instance: Instance<'tcx>, kind: &CoverageKind) {
"ConditionId of evaluated conditions should never be zero" "ConditionId of evaluated conditions should never be zero"
); );
let cond_bitmap = coverage_context let cond_bitmap = coverage_context
.try_get_mcdc_condition_bitmap(&instance, 0) .try_get_mcdc_condition_bitmap(&instance, decision_depth)
.expect("mcdc cond bitmap should have been allocated for updating"); .expect("mcdc cond bitmap should have been allocated for updating");
let cond_loc = bx.const_i32(id.as_u32() as i32 - 1); let cond_loc = bx.const_i32(id.as_u32() as i32 - 1);
let bool_value = bx.const_bool(value); let bool_value = bx.const_bool(value);
@ -170,10 +170,10 @@ fn add_coverage(&mut self, instance: Instance<'tcx>, kind: &CoverageKind) {
let hash = bx.const_u64(function_coverage_info.function_source_hash); let hash = bx.const_u64(function_coverage_info.function_source_hash);
bx.mcdc_condbitmap_update(fn_name, hash, cond_loc, cond_bitmap, bool_value); bx.mcdc_condbitmap_update(fn_name, hash, cond_loc, cond_bitmap, bool_value);
} }
CoverageKind::TestVectorBitmapUpdate { bitmap_idx } => { CoverageKind::TestVectorBitmapUpdate { bitmap_idx, decision_depth } => {
drop(coverage_map); drop(coverage_map);
let cond_bitmap = coverage_context let cond_bitmap = coverage_context
.try_get_mcdc_condition_bitmap(&instance, 0) .try_get_mcdc_condition_bitmap(&instance, decision_depth)
.expect("mcdc cond bitmap should have been allocated for merging into the global bitmap"); .expect("mcdc cond bitmap should have been allocated for merging into the global bitmap");
let bitmap_bytes = bx.tcx().coverage_ids_info(instance.def).mcdc_bitmap_bytes; let bitmap_bytes = bx.tcx().coverage_ids_info(instance.def).mcdc_bitmap_bytes;
assert!(bitmap_idx < bitmap_bytes, "bitmap index of the decision out of range"); assert!(bitmap_idx < bitmap_bytes, "bitmap index of the decision out of range");

View File

@ -132,7 +132,7 @@ pub enum CoverageKind {
/// ///
/// If this statement does not survive MIR optimizations, the condition would never be /// If this statement does not survive MIR optimizations, the condition would never be
/// taken as evaluated. /// taken as evaluated.
CondBitmapUpdate { id: ConditionId, value: bool }, CondBitmapUpdate { id: ConditionId, value: bool, decision_depth: u16 },
/// Marks the point in MIR control flow represented by a evaluated decision. /// Marks the point in MIR control flow represented by a evaluated decision.
/// ///
@ -140,7 +140,7 @@ pub enum CoverageKind {
/// ///
/// If this statement does not survive MIR optimizations, the decision would never be /// If this statement does not survive MIR optimizations, the decision would never be
/// taken as evaluated. /// taken as evaluated.
TestVectorBitmapUpdate { bitmap_idx: u32 }, TestVectorBitmapUpdate { bitmap_idx: u32, decision_depth: u16 },
} }
impl Debug for CoverageKind { impl Debug for CoverageKind {
@ -151,11 +151,17 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
BlockMarker { id } => write!(fmt, "BlockMarker({:?})", id.index()), BlockMarker { id } => write!(fmt, "BlockMarker({:?})", id.index()),
CounterIncrement { id } => write!(fmt, "CounterIncrement({:?})", id.index()), CounterIncrement { id } => write!(fmt, "CounterIncrement({:?})", id.index()),
ExpressionUsed { id } => write!(fmt, "ExpressionUsed({:?})", id.index()), ExpressionUsed { id } => write!(fmt, "ExpressionUsed({:?})", id.index()),
CondBitmapUpdate { id, value } => { CondBitmapUpdate { id, value, decision_depth } => {
write!(fmt, "CondBitmapUpdate({:?}, {:?})", id.index(), value) write!(
fmt,
"CondBitmapUpdate({:?}, {:?}, depth={:?})",
id.index(),
value,
decision_depth
)
} }
TestVectorBitmapUpdate { bitmap_idx } => { TestVectorBitmapUpdate { bitmap_idx, decision_depth } => {
write!(fmt, "TestVectorUpdate({:?})", bitmap_idx) write!(fmt, "TestVectorUpdate({:?}, depth={:?})", bitmap_idx, decision_depth)
} }
} }
} }
@ -319,6 +325,7 @@ pub struct MCDCBranchSpan {
pub condition_info: Option<ConditionInfo>, pub condition_info: Option<ConditionInfo>,
pub true_marker: BlockMarkerId, pub true_marker: BlockMarkerId,
pub false_marker: BlockMarkerId, pub false_marker: BlockMarkerId,
pub decision_depth: u16,
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
@ -334,4 +341,5 @@ pub struct MCDCDecisionSpan {
pub span: Span, pub span: Span,
pub conditions_num: usize, pub conditions_num: usize,
pub end_markers: Vec<BlockMarkerId>, pub end_markers: Vec<BlockMarkerId>,
pub decision_depth: u16,
} }

View File

@ -496,20 +496,27 @@ fn write_coverage_branch_info(
)?; )?;
} }
for coverage::MCDCBranchSpan { span, condition_info, true_marker, false_marker } in for coverage::MCDCBranchSpan {
mcdc_branch_spans span,
condition_info,
true_marker,
false_marker,
decision_depth,
} in mcdc_branch_spans
{ {
writeln!( writeln!(
w, w,
"{INDENT}coverage mcdc branch {{ condition_id: {:?}, true: {true_marker:?}, false: {false_marker:?} }} => {span:?}", "{INDENT}coverage mcdc branch {{ condition_id: {:?}, true: {true_marker:?}, false: {false_marker:?}, depth: {decision_depth:?} }} => {span:?}",
condition_info.map(|info| info.condition_id) condition_info.map(|info| info.condition_id)
)?; )?;
} }
for coverage::MCDCDecisionSpan { span, conditions_num, end_markers } in mcdc_decision_spans { for coverage::MCDCDecisionSpan { span, conditions_num, end_markers, decision_depth } in
mcdc_decision_spans
{
writeln!( writeln!(
w, w,
"{INDENT}coverage mcdc decision {{ conditions_num: {conditions_num:?}, end: {end_markers:?} }} => {span:?}" "{INDENT}coverage mcdc decision {{ conditions_num: {conditions_num:?}, end: {end_markers:?}, depth: {decision_depth:?} }} => {span:?}"
)?; )?;
} }

View File

@ -262,6 +262,7 @@ fn record_conditions(&mut self, op: LogicalOp, span: Span) {
span, span,
conditions_num: 0, conditions_num: 0,
end_markers: vec![], end_markers: vec![],
decision_depth: 0,
}), }),
}; };
@ -371,6 +372,7 @@ pub(crate) fn visit_coverage_branch_condition(
condition_info, condition_info,
true_marker, true_marker,
false_marker, false_marker,
decision_depth: 0,
}); });
return; return;
} }

View File

@ -145,16 +145,17 @@ fn create_mappings<'tcx>(
|BcbMapping { kind: bcb_mapping_kind, span }| { |BcbMapping { kind: bcb_mapping_kind, span }| {
let kind = match *bcb_mapping_kind { let kind = match *bcb_mapping_kind {
BcbMappingKind::Code(bcb) => MappingKind::Code(term_for_bcb(bcb)), BcbMappingKind::Code(bcb) => MappingKind::Code(term_for_bcb(bcb)),
BcbMappingKind::MCDCBranch { true_bcb, false_bcb, condition_info: None } => { BcbMappingKind::MCDCBranch {
MappingKind::Branch { true_bcb, false_bcb, condition_info: None, ..
true_term: term_for_bcb(true_bcb), } => MappingKind::Branch {
false_term: term_for_bcb(false_bcb), true_term: term_for_bcb(true_bcb),
} false_term: term_for_bcb(false_bcb),
} },
BcbMappingKind::MCDCBranch { BcbMappingKind::MCDCBranch {
true_bcb, true_bcb,
false_bcb, false_bcb,
condition_info: Some(mcdc_params), condition_info: Some(mcdc_params),
..
} => MappingKind::MCDCBranch { } => MappingKind::MCDCBranch {
true_term: term_for_bcb(true_bcb), true_term: term_for_bcb(true_bcb),
false_term: term_for_bcb(false_bcb), false_term: term_for_bcb(false_bcb),
@ -246,24 +247,28 @@ fn inject_mcdc_statements<'tcx>(
} }
// Inject test vector update first because `inject_statement` always insert new statement at head. // Inject test vector update first because `inject_statement` always insert new statement at head.
for (end_bcbs, bitmap_idx) in for (end_bcbs, bitmap_idx, decision_depth) in
coverage_spans.mappings.iter().filter_map(|mapping| match &mapping.kind { coverage_spans.mappings.iter().filter_map(|mapping| match &mapping.kind {
BcbMappingKind::MCDCDecision { end_bcbs, bitmap_idx, .. } => { BcbMappingKind::MCDCDecision { end_bcbs, bitmap_idx, decision_depth, .. } => {
Some((end_bcbs, *bitmap_idx)) Some((end_bcbs, *bitmap_idx, *decision_depth))
} }
_ => None, _ => None,
}) })
{ {
for end in end_bcbs { for end in end_bcbs {
let end_bb = basic_coverage_blocks[*end].leader_bb(); let end_bb = basic_coverage_blocks[*end].leader_bb();
inject_statement(mir_body, CoverageKind::TestVectorBitmapUpdate { bitmap_idx }, end_bb); inject_statement(
mir_body,
CoverageKind::TestVectorBitmapUpdate { bitmap_idx, decision_depth },
end_bb,
);
} }
} }
for (true_bcb, false_bcb, condition_id) in for (true_bcb, false_bcb, condition_id, decision_depth) in
coverage_spans.mappings.iter().filter_map(|mapping| match mapping.kind { coverage_spans.mappings.iter().filter_map(|mapping| match mapping.kind {
BcbMappingKind::MCDCBranch { true_bcb, false_bcb, condition_info } => { BcbMappingKind::MCDCBranch { true_bcb, false_bcb, condition_info, decision_depth } => {
Some((true_bcb, false_bcb, condition_info?.condition_id)) Some((true_bcb, false_bcb, condition_info?.condition_id, decision_depth))
} }
_ => None, _ => None,
}) })
@ -271,13 +276,13 @@ fn inject_mcdc_statements<'tcx>(
let true_bb = basic_coverage_blocks[true_bcb].leader_bb(); let true_bb = basic_coverage_blocks[true_bcb].leader_bb();
inject_statement( inject_statement(
mir_body, mir_body,
CoverageKind::CondBitmapUpdate { id: condition_id, value: true }, CoverageKind::CondBitmapUpdate { id: condition_id, value: true, decision_depth },
true_bb, true_bb,
); );
let false_bb = basic_coverage_blocks[false_bcb].leader_bb(); let false_bb = basic_coverage_blocks[false_bcb].leader_bb();
inject_statement( inject_statement(
mir_body, mir_body,
CoverageKind::CondBitmapUpdate { id: condition_id, value: false }, CoverageKind::CondBitmapUpdate { id: condition_id, value: false, decision_depth },
false_bb, false_bb,
); );
} }

View File

@ -26,9 +26,15 @@ pub(super) enum BcbMappingKind {
/// If `None`, this actually represents a normal branch mapping inserted /// If `None`, this actually represents a normal branch mapping inserted
/// for code that was too complex for MC/DC. /// for code that was too complex for MC/DC.
condition_info: Option<ConditionInfo>, condition_info: Option<ConditionInfo>,
decision_depth: u16,
}, },
/// Associates a mcdc decision with its join BCB. /// Associates a mcdc decision with its join BCB.
MCDCDecision { end_bcbs: BTreeSet<BasicCoverageBlock>, bitmap_idx: u32, conditions_num: u16 }, MCDCDecision {
end_bcbs: BTreeSet<BasicCoverageBlock>,
bitmap_idx: u32,
conditions_num: u16,
decision_depth: u16,
},
} }
#[derive(Debug)] #[derive(Debug)]

View File

@ -453,15 +453,25 @@ pub(super) fn extract_mcdc_mappings(
Some((span, true_bcb, false_bcb)) Some((span, true_bcb, false_bcb))
}; };
let mcdc_branch_filter_map = let mcdc_branch_filter_map = |&MCDCBranchSpan {
|&MCDCBranchSpan { span: raw_span, true_marker, false_marker, condition_info }| { span: raw_span,
check_branch_bcb(raw_span, true_marker, false_marker).map( true_marker,
|(span, true_bcb, false_bcb)| BcbMapping { false_marker,
kind: BcbMappingKind::MCDCBranch { true_bcb, false_bcb, condition_info }, condition_info,
span, decision_depth,
}| {
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,
decision_depth,
}, },
) span,
}; }
})
};
let mut next_bitmap_idx = 0; let mut next_bitmap_idx = 0;
@ -482,6 +492,7 @@ pub(super) fn extract_mcdc_mappings(
end_bcbs, end_bcbs,
bitmap_idx, bitmap_idx,
conditions_num: decision.conditions_num as u16, conditions_num: decision.conditions_num as u16,
decision_depth: decision.decision_depth,
}, },
span, span,
}) })