1
Fork 0

coverage. Adapt to mcdc mapping formats introduced by llvm 19

This commit is contained in:
zhuyunxing 2024-07-25 15:23:35 +08:00
parent 99bd601df5
commit 6e3e19f714
22 changed files with 490 additions and 485 deletions

View file

@ -114,16 +114,16 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir:
inject_mcdc_statements(mir_body, &basic_coverage_blocks, &extracted_mappings);
let mcdc_num_condition_bitmaps = extracted_mappings
.mcdc_decisions
.mcdc_mappings
.iter()
.map(|&mappings::MCDCDecision { decision_depth, .. }| decision_depth)
.map(|&(mappings::MCDCDecision { decision_depth, .. }, _)| decision_depth)
.max()
.map_or(0, |max| usize::from(max) + 1);
mir_body.function_coverage_info = Some(Box::new(FunctionCoverageInfo {
function_source_hash: hir_info.function_source_hash,
num_counters: coverage_counters.num_counters(),
mcdc_bitmap_bytes: extracted_mappings.mcdc_bitmap_bytes,
mcdc_bitmap_bits: extracted_mappings.mcdc_bitmap_bits,
expressions: coverage_counters.into_expressions(),
mappings,
mcdc_num_condition_bitmaps,
@ -161,9 +161,9 @@ fn create_mappings<'tcx>(
num_bcbs: _,
code_mappings,
branch_pairs,
mcdc_bitmap_bytes: _,
mcdc_branches,
mcdc_decisions,
mcdc_bitmap_bits: _,
mcdc_degraded_branches,
mcdc_mappings,
} = extracted_mappings;
let mut mappings = Vec::new();
@ -186,26 +186,79 @@ fn create_mappings<'tcx>(
},
));
mappings.extend(mcdc_branches.iter().filter_map(
|&mappings::MCDCBranch { span, true_bcb, false_bcb, condition_info, decision_depth: _ }| {
let term_for_bcb =
|bcb| coverage_counters.term_for_bcb(bcb).expect("all BCBs with spans were given counters");
// MCDC branch mappings are appended with their decisions in case decisions were ignored.
mappings.extend(mcdc_degraded_branches.iter().filter_map(
|&mappings::MCDCBranch {
span,
true_bcb,
false_bcb,
condition_info: _,
true_index: _,
false_index: _,
}| {
let source_region = region_for_span(span)?;
let true_term = term_for_bcb(true_bcb);
let false_term = term_for_bcb(false_bcb);
let kind = match condition_info {
Some(mcdc_params) => MappingKind::MCDCBranch { true_term, false_term, mcdc_params },
None => MappingKind::Branch { true_term, false_term },
};
Some(Mapping { kind, source_region })
Some(Mapping { kind: MappingKind::Branch { true_term, false_term }, source_region })
},
));
mappings.extend(mcdc_decisions.iter().filter_map(
|&mappings::MCDCDecision { span, bitmap_idx, num_conditions, .. }| {
let source_region = region_for_span(span)?;
let kind = MappingKind::MCDCDecision(DecisionInfo { bitmap_idx, num_conditions });
Some(Mapping { kind, source_region })
},
));
for (decision, branches) in mcdc_mappings {
let num_conditions = branches.len() as u16;
let conditions = branches
.into_iter()
.filter_map(
|&mappings::MCDCBranch {
span,
true_bcb,
false_bcb,
condition_info,
true_index: _,
false_index: _,
}| {
let source_region = region_for_span(span)?;
let true_term = term_for_bcb(true_bcb);
let false_term = term_for_bcb(false_bcb);
Some(Mapping {
kind: MappingKind::MCDCBranch {
true_term,
false_term,
mcdc_params: condition_info,
},
source_region,
})
},
)
.collect::<Vec<_>>();
if conditions.len() == num_conditions as usize
&& let Some(source_region) = region_for_span(decision.span)
{
// LLVM requires end index for counter mapping regions.
let kind = MappingKind::MCDCDecision(DecisionInfo {
bitmap_idx: (decision.bitmap_idx + decision.num_test_vectors) as u32,
num_conditions,
});
mappings.extend(
std::iter::once(Mapping { kind, source_region }).chain(conditions.into_iter()),
);
} else {
mappings.extend(conditions.into_iter().map(|mapping| {
let MappingKind::MCDCBranch { true_term, false_term, mcdc_params: _ } =
mapping.kind
else {
unreachable!("all mappings here are MCDCBranch as shown above");
};
Mapping {
kind: MappingKind::Branch { true_term, false_term },
source_region: mapping.source_region,
}
}))
}
}
mappings
}
@ -274,44 +327,41 @@ fn inject_mcdc_statements<'tcx>(
basic_coverage_blocks: &CoverageGraph,
extracted_mappings: &ExtractedMappings,
) {
// Inject test vector update first because `inject_statement` always insert new statement at
// head.
for &mappings::MCDCDecision {
span: _,
ref end_bcbs,
bitmap_idx,
num_conditions: _,
decision_depth,
} in &extracted_mappings.mcdc_decisions
{
for end in end_bcbs {
let end_bb = basic_coverage_blocks[*end].leader_bb();
for (decision, conditions) in &extracted_mappings.mcdc_mappings {
// Inject test vector update first because `inject_statement` always insert new statement at head.
for &end in &decision.end_bcbs {
let end_bb = basic_coverage_blocks[end].leader_bb();
inject_statement(
mir_body,
CoverageKind::TestVectorBitmapUpdate { bitmap_idx, decision_depth },
CoverageKind::TestVectorBitmapUpdate {
bitmap_idx: decision.bitmap_idx as u32,
decision_depth: decision.decision_depth,
},
end_bb,
);
}
}
for &mappings::MCDCBranch { span: _, true_bcb, false_bcb, condition_info, decision_depth } in
&extracted_mappings.mcdc_branches
{
let Some(condition_info) = condition_info else { continue };
let id = condition_info.condition_id;
let true_bb = basic_coverage_blocks[true_bcb].leader_bb();
inject_statement(
mir_body,
CoverageKind::CondBitmapUpdate { id, value: true, decision_depth },
true_bb,
);
let false_bb = basic_coverage_blocks[false_bcb].leader_bb();
inject_statement(
mir_body,
CoverageKind::CondBitmapUpdate { id, value: false, decision_depth },
false_bb,
);
for &mappings::MCDCBranch {
span: _,
true_bcb,
false_bcb,
condition_info: _,
true_index,
false_index,
} in conditions
{
for (index, bcb) in [(false_index, false_bcb), (true_index, true_bcb)] {
let bb = basic_coverage_blocks[bcb].leader_bb();
inject_statement(
mir_body,
CoverageKind::CondBitmapUpdate {
index: index as u32,
decision_depth: decision.decision_depth,
},
bb,
);
}
}
}
}