coverage: Let each coverage statement hold a vector of code regions

This makes it possible for a `StatementKind::Coverage` to hold more than one
code region, but that capability is not yet used.
This commit is contained in:
Zalathar 2023-08-27 17:11:13 +10:00
parent 1355e1fc74
commit ee9d00f6b8
9 changed files with 96 additions and 90 deletions

View file

@ -243,7 +243,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
self.mir_body,
self.make_mir_coverage_kind(&counter_kind),
self.bcb_leader_bb(bcb),
Some(code_region),
vec![code_region],
);
}
}
@ -302,7 +302,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
self.mir_body,
self.make_mir_coverage_kind(&counter_kind),
inject_to_bb,
None,
Vec::new(),
);
}
BcbCounter::Expression { .. } => inject_intermediate_expression(
@ -367,20 +367,14 @@ fn inject_statement(
mir_body: &mut mir::Body<'_>,
counter_kind: CoverageKind,
bb: BasicBlock,
some_code_region: Option<CodeRegion>,
code_regions: Vec<CodeRegion>,
) {
debug!(
" injecting statement {:?} for {:?} at code region: {:?}",
counter_kind, bb, some_code_region
);
debug!(" injecting statement {counter_kind:?} for {bb:?} at code regions: {code_regions:?}");
let data = &mut mir_body[bb];
let source_info = data.terminator().source_info;
let statement = Statement {
source_info,
kind: StatementKind::Coverage(Box::new(Coverage {
kind: counter_kind,
code_region: some_code_region,
})),
kind: StatementKind::Coverage(Box::new(Coverage { kind: counter_kind, code_regions })),
};
data.statements.insert(0, statement);
}
@ -394,7 +388,10 @@ fn inject_intermediate_expression(mir_body: &mut mir::Body<'_>, expression: Cove
let source_info = data.terminator().source_info;
let statement = Statement {
source_info,
kind: StatementKind::Coverage(Box::new(Coverage { kind: expression, code_region: None })),
kind: StatementKind::Coverage(Box::new(Coverage {
kind: expression,
code_regions: Vec::new(),
})),
};
data.statements.push(statement);
}

View file

@ -93,8 +93,8 @@ fn coverageinfo<'tcx>(tcx: TyCtxt<'tcx>, instance_def: ty::InstanceDef<'tcx>) ->
fn covered_code_regions(tcx: TyCtxt<'_>, def_id: DefId) -> Vec<&CodeRegion> {
let body = mir_body(tcx, def_id);
all_coverage_in_mir_body(body)
// Not all coverage statements have an attached code region.
.filter_map(|coverage| coverage.code_region.as_ref())
// Coverage statements have a list of code regions (possibly empty).
.flat_map(|coverage| coverage.code_regions.as_slice())
.collect()
}

View file

@ -441,21 +441,23 @@ fn save_unreachable_coverage(
let dead_block = &basic_blocks[dead_block];
for statement in &dead_block.statements {
let StatementKind::Coverage(coverage) = &statement.kind else { continue };
let Some(code_region) = &coverage.code_region else { continue };
if coverage.code_regions.is_empty() {
continue;
};
let instance = statement.source_info.scope.inlined_instance(source_scopes);
if live.contains(&instance) {
retained_coverage.push((statement.source_info, code_region.clone()));
retained_coverage.push((statement.source_info, coverage.code_regions.clone()));
}
}
}
let start_block = &mut basic_blocks[START_BLOCK];
start_block.statements.extend(retained_coverage.into_iter().map(
|(source_info, code_region)| Statement {
|(source_info, code_regions)| Statement {
source_info,
kind: StatementKind::Coverage(Box::new(Coverage {
kind: CoverageKind::Unreachable,
code_region: Some(code_region),
code_regions,
})),
},
));