1
Fork 0

Narrow trait CoverageInfoBuilderMethods down to just one method

This effectively inlines most of `FunctionCx::codegen_coverage` into the LLVM
implementation of `CoverageInfoBuilderMethods`.
This commit is contained in:
Zalathar 2023-07-05 17:39:40 +10:00
parent 6dab6dc5fc
commit 4169d0f756
5 changed files with 69 additions and 102 deletions

View file

@ -1,40 +1,15 @@
use gccjit::RValue; use gccjit::RValue;
use rustc_codegen_ssa::traits::{CoverageInfoBuilderMethods, CoverageInfoMethods}; use rustc_codegen_ssa::traits::{CoverageInfoBuilderMethods, CoverageInfoMethods};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_middle::mir::coverage::{ use rustc_middle::mir::Coverage;
CodeRegion,
CounterValueReference,
ExpressionOperandId,
InjectedExpressionId,
Op,
};
use rustc_middle::ty::Instance; use rustc_middle::ty::Instance;
use crate::builder::Builder; use crate::builder::Builder;
use crate::context::CodegenCx; use crate::context::CodegenCx;
impl<'a, 'gcc, 'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { impl<'a, 'gcc, 'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
fn set_function_source_hash( fn add_coverage(&mut self, _instance: Instance<'tcx>, _coverage: &Coverage) {
&mut self,
_instance: Instance<'tcx>,
_function_source_hash: u64,
) -> bool {
unimplemented!();
}
fn add_coverage_counter(&mut self, _instance: Instance<'tcx>, _id: CounterValueReference, _region: CodeRegion) -> bool {
// TODO(antoyo) // TODO(antoyo)
false
}
fn add_coverage_counter_expression(&mut self, _instance: Instance<'tcx>, _id: InjectedExpressionId, _lhs: ExpressionOperandId, _op: Op, _rhs: ExpressionOperandId, _region: Option<CodeRegion>) -> bool {
// TODO(antoyo)
false
}
fn add_coverage_unreachable(&mut self, _instance: Instance<'tcx>, _region: CodeRegion) -> bool {
// TODO(antoyo)
false
} }
} }

View file

@ -17,10 +17,11 @@ use rustc_hir::def_id::DefId;
use rustc_llvm::RustString; use rustc_llvm::RustString;
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::mir::coverage::{ use rustc_middle::mir::coverage::{
CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId, Op, CodeRegion, CounterValueReference, CoverageKind, ExpressionOperandId, InjectedExpressionId, Op,
}; };
use rustc_middle::mir::Coverage;
use rustc_middle::ty; use rustc_middle::ty;
use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::Instance; use rustc_middle::ty::Instance;
@ -94,6 +95,54 @@ impl<'ll, 'tcx> CoverageInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
} }
impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
fn add_coverage(&mut self, instance: Instance<'tcx>, coverage: &Coverage) {
let bx = self;
let Coverage { kind, code_region } = coverage.clone();
match kind {
CoverageKind::Counter { function_source_hash, id } => {
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(instance, id, code_region);
}
let coverageinfo = bx.tcx().coverageinfo(instance.def);
let fn_name = bx.get_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(id.zero_based_index());
debug!(
"codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})",
fn_name, hash, num_counters, index,
);
bx.instrprof_increment(fn_name, hash, num_counters, index);
}
}
CoverageKind::Expression { id, lhs, op, rhs } => {
bx.add_coverage_counter_expression(instance, id, lhs, op, rhs, code_region);
}
CoverageKind::Unreachable => {
bx.add_coverage_unreachable(
instance,
code_region.expect("unreachable regions always have code regions"),
);
}
}
}
}
// These methods used to be part of trait `CoverageInfoBuilderMethods`, but
// after moving most coverage code out of SSA they are now just ordinary methods.
impl<'tcx> Builder<'_, '_, 'tcx> {
/// Returns true if the function source hash was added to the coverage map (even if it had
/// already been added, for this instance). Returns false *only* if `-C instrument-coverage` is
/// not enabled (a coverage map is not being generated).
fn set_function_source_hash( fn set_function_source_hash(
&mut self, &mut self,
instance: Instance<'tcx>, instance: Instance<'tcx>,
@ -115,6 +164,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
} }
} }
/// Returns true if the counter was added to the coverage map; false if `-C instrument-coverage`
/// is not enabled (a coverage map is not being generated).
fn add_coverage_counter( fn add_coverage_counter(
&mut self, &mut self,
instance: Instance<'tcx>, instance: Instance<'tcx>,
@ -137,6 +188,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
} }
} }
/// Returns true if the expression was added to the coverage map; false if
/// `-C instrument-coverage` is not enabled (a coverage map is not being generated).
fn add_coverage_counter_expression( fn add_coverage_counter_expression(
&mut self, &mut self,
instance: Instance<'tcx>, instance: Instance<'tcx>,
@ -163,6 +216,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
} }
} }
/// Returns true if the region was added to the coverage map; false if `-C instrument-coverage`
/// is not enabled (a coverage map is not being generated).
fn add_coverage_unreachable(&mut self, instance: Instance<'tcx>, region: CodeRegion) -> bool { fn add_coverage_unreachable(&mut self, instance: Instance<'tcx>, region: CodeRegion) -> bool {
if let Some(coverage_context) = self.coverage_context() { if let Some(coverage_context) = self.coverage_context() {
debug!( debug!(

View file

@ -1,13 +1,12 @@
use crate::traits::*; use crate::traits::*;
use rustc_middle::mir::coverage::*;
use rustc_middle::mir::Coverage; use rustc_middle::mir::Coverage;
use rustc_middle::mir::SourceScope; use rustc_middle::mir::SourceScope;
use super::FunctionCx; use super::FunctionCx;
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
pub fn codegen_coverage(&self, bx: &mut Bx, coverage: Coverage, scope: SourceScope) { pub fn codegen_coverage(&self, bx: &mut Bx, coverage: &Coverage, scope: SourceScope) {
// Determine the instance that coverage data was originally generated for. // Determine the instance that coverage data was originally generated for.
let instance = if let Some(inlined) = scope.inlined_instance(&self.mir.source_scopes) { let instance = if let Some(inlined) = scope.inlined_instance(&self.mir.source_scopes) {
self.monomorphize(inlined) self.monomorphize(inlined)
@ -15,41 +14,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
self.instance self.instance
}; };
let Coverage { kind, code_region } = coverage; // Handle the coverage info in a backend-specific way.
match kind { bx.add_coverage(instance, coverage);
CoverageKind::Counter { function_source_hash, id } => {
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(instance, id, code_region);
}
let coverageinfo = bx.tcx().coverageinfo(instance.def);
let fn_name = bx.get_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(id.zero_based_index());
debug!(
"codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})",
fn_name, hash, num_counters, index,
);
bx.instrprof_increment(fn_name, hash, num_counters, index);
}
}
CoverageKind::Expression { id, lhs, op, rhs } => {
bx.add_coverage_counter_expression(instance, id, lhs, op, rhs, code_region);
}
CoverageKind::Unreachable => {
bx.add_coverage_unreachable(
instance,
code_region.expect("unreachable regions always have code regions"),
);
}
}
} }
} }

View file

@ -65,7 +65,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
} }
} }
mir::StatementKind::Coverage(box ref coverage) => { mir::StatementKind::Coverage(box ref coverage) => {
self.codegen_coverage(bx, coverage.clone(), statement.source_info.scope); self.codegen_coverage(bx, coverage, statement.source_info.scope);
} }
mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(ref op)) => { mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(ref op)) => {
let op_val = self.codegen_operand(bx, op); let op_val = self.codegen_operand(bx, op);

View file

@ -1,6 +1,6 @@
use super::BackendTypes; use super::BackendTypes;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_middle::mir::coverage::*; use rustc_middle::mir::Coverage;
use rustc_middle::ty::Instance; use rustc_middle::ty::Instance;
pub trait CoverageInfoMethods<'tcx>: BackendTypes { pub trait CoverageInfoMethods<'tcx>: BackendTypes {
@ -21,37 +21,9 @@ pub trait CoverageInfoMethods<'tcx>: BackendTypes {
} }
pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes { pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes {
/// Returns true if the function source hash was added to the coverage map (even if it had /// Handle the MIR coverage info in a backend-specific way.
/// already been added, for this instance). Returns false *only* if `-C instrument-coverage` is ///
/// not enabled (a coverage map is not being generated). /// This can potentially be a no-op in backends that don't support
fn set_function_source_hash( /// coverage instrumentation.
&mut self, fn add_coverage(&mut self, instance: Instance<'tcx>, coverage: &Coverage);
instance: Instance<'tcx>,
function_source_hash: u64,
) -> bool;
/// Returns true if the counter was added to the coverage map; false if `-C instrument-coverage`
/// is not enabled (a coverage map is not being generated).
fn add_coverage_counter(
&mut self,
instance: Instance<'tcx>,
index: CounterValueReference,
region: CodeRegion,
) -> bool;
/// Returns true if the expression was added to the coverage map; false if
/// `-C instrument-coverage` is not enabled (a coverage map is not being generated).
fn add_coverage_counter_expression(
&mut self,
instance: Instance<'tcx>,
id: InjectedExpressionId,
lhs: ExpressionOperandId,
op: Op,
rhs: ExpressionOperandId,
region: Option<CodeRegion>,
) -> bool;
/// Returns true if the region was added to the coverage map; false if `-C instrument-coverage`
/// is not enabled (a coverage map is not being generated).
fn add_coverage_unreachable(&mut self, instance: Instance<'tcx>, region: CodeRegion) -> bool;
} }