Rollup merge of #83080 - tmiasko:inline-coverage, r=wesleywiser
Make source-based code coverage compatible with MIR inlining When codegenning code coverage use the instance that coverage data was originally generated for, to ensure basic level of compatibility with MIR inlining. Fixes #83061
This commit is contained in:
commit
b688b694d0
25 changed files with 1100 additions and 88 deletions
|
@ -8,7 +8,7 @@ use rustc_middle::mir::coverage::{
|
|||
use rustc_middle::ty::Instance;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Expression {
|
||||
lhs: ExpressionOperandId,
|
||||
op: Op,
|
||||
|
@ -64,7 +64,9 @@ impl<'tcx> FunctionCoverage<'tcx> {
|
|||
|
||||
/// Adds a code region to be counted by an injected counter intrinsic.
|
||||
pub fn add_counter(&mut self, id: CounterValueReference, region: CodeRegion) {
|
||||
self.counters[id].replace(region).expect_none("add_counter called with duplicate `id`");
|
||||
if let Some(previous_region) = self.counters[id].replace(region.clone()) {
|
||||
assert_eq!(previous_region, region, "add_counter: code region for id changed");
|
||||
}
|
||||
}
|
||||
|
||||
/// Both counters and "counter expressions" (or simply, "expressions") can be operands in other
|
||||
|
@ -94,9 +96,18 @@ impl<'tcx> FunctionCoverage<'tcx> {
|
|||
expression_id, lhs, op, rhs, region
|
||||
);
|
||||
let expression_index = self.expression_index(u32::from(expression_id));
|
||||
self.expressions[expression_index]
|
||||
.replace(Expression { lhs, op, rhs, region })
|
||||
.expect_none("add_counter_expression called with duplicate `id_descending_from_max`");
|
||||
if let Some(previous_expression) = self.expressions[expression_index].replace(Expression {
|
||||
lhs,
|
||||
op,
|
||||
rhs,
|
||||
region: region.clone(),
|
||||
}) {
|
||||
assert_eq!(
|
||||
previous_expression,
|
||||
Expression { lhs, op, rhs, region },
|
||||
"add_counter_expression: expression for id changed"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a region that will be marked as "unreachable", with a constant "zero counter".
|
||||
|
|
|
@ -2,27 +2,38 @@ use crate::traits::*;
|
|||
|
||||
use rustc_middle::mir::coverage::*;
|
||||
use rustc_middle::mir::Coverage;
|
||||
use rustc_middle::mir::SourceScope;
|
||||
|
||||
use super::FunctionCx;
|
||||
|
||||
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
pub fn codegen_coverage(&self, bx: &mut Bx, coverage: Coverage) {
|
||||
pub fn codegen_coverage(&self, bx: &mut Bx, coverage: Coverage, scope: SourceScope) {
|
||||
// Determine the instance that coverage data was originally generated for.
|
||||
let scope_data = &self.mir.source_scopes[scope];
|
||||
let instance = if let Some((inlined_instance, _)) = scope_data.inlined {
|
||||
self.monomorphize(inlined_instance)
|
||||
} else if let Some(inlined_scope) = scope_data.inlined_parent_scope {
|
||||
self.monomorphize(self.mir.source_scopes[inlined_scope].inlined.unwrap().0)
|
||||
} else {
|
||||
self.instance
|
||||
};
|
||||
|
||||
let Coverage { kind, code_region } = coverage;
|
||||
match kind {
|
||||
CoverageKind::Counter { function_source_hash, id } => {
|
||||
if bx.set_function_source_hash(self.instance, function_source_hash) {
|
||||
if bx.set_function_source_hash(instance, function_source_hash) {
|
||||
// If `set_function_source_hash()` returned true, the coverage map is enabled,
|
||||
// so continue adding the counter.
|
||||
if let Some(code_region) = code_region {
|
||||
// Note: Some counters do not have code regions, but may still be referenced
|
||||
// from expressions. In that case, don't add the counter to the coverage map,
|
||||
// but do inject the counter intrinsic.
|
||||
bx.add_coverage_counter(self.instance, id, code_region);
|
||||
bx.add_coverage_counter(instance, id, code_region);
|
||||
}
|
||||
|
||||
let coverageinfo = bx.tcx().coverageinfo(self.instance.def_id());
|
||||
let coverageinfo = bx.tcx().coverageinfo(instance.def_id());
|
||||
|
||||
let fn_name = bx.create_pgo_func_name_var(self.instance);
|
||||
let fn_name = bx.create_pgo_func_name_var(instance);
|
||||
let hash = bx.const_u64(function_source_hash);
|
||||
let num_counters = bx.const_u32(coverageinfo.num_counters);
|
||||
let index = bx.const_u32(u32::from(id));
|
||||
|
@ -34,11 +45,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
}
|
||||
CoverageKind::Expression { id, lhs, op, rhs } => {
|
||||
bx.add_coverage_counter_expression(self.instance, id, lhs, op, rhs, code_region);
|
||||
bx.add_coverage_counter_expression(instance, id, lhs, op, rhs, code_region);
|
||||
}
|
||||
CoverageKind::Unreachable => {
|
||||
bx.add_coverage_unreachable(
|
||||
self.instance,
|
||||
instance,
|
||||
code_region.expect("unreachable regions always have code regions"),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
bx
|
||||
}
|
||||
mir::StatementKind::Coverage(box ref coverage) => {
|
||||
self.codegen_coverage(&mut bx, coverage.clone());
|
||||
self.codegen_coverage(&mut bx, coverage.clone(), statement.source_info.scope);
|
||||
bx
|
||||
}
|
||||
mir::StatementKind::CopyNonOverlapping(box mir::CopyNonOverlapping {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue