1
Fork 0

coverage: Make obtaining the codegen coverage context infallible

In all the situations where this context is needed, it should always be
available.
This commit is contained in:
Zalathar 2024-10-24 22:23:13 +11:00
parent 9f8a6be221
commit 0a96176533
3 changed files with 16 additions and 33 deletions

View file

@ -80,6 +80,7 @@ pub(crate) struct CodegenCx<'ll, 'tcx> {
pub isize_ty: &'ll Type, pub isize_ty: &'ll Type,
/// Extra codegen state needed when coverage instrumentation is enabled.
pub coverage_cx: Option<coverageinfo::CrateCoverageContext<'ll, 'tcx>>, pub coverage_cx: Option<coverageinfo::CrateCoverageContext<'ll, 'tcx>>,
pub dbg_cx: Option<debuginfo::CodegenUnitDebugContext<'ll, 'tcx>>, pub dbg_cx: Option<debuginfo::CodegenUnitDebugContext<'ll, 'tcx>>,
@ -592,11 +593,10 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
&self.statics_to_rauw &self.statics_to_rauw
} }
/// Extra state that is only available when coverage instrumentation is enabled.
#[inline] #[inline]
pub(crate) fn coverage_context( pub(crate) fn coverage_cx(&self) -> &coverageinfo::CrateCoverageContext<'ll, 'tcx> {
&self, self.coverage_cx.as_ref().expect("only called when coverage instrumentation is enabled")
) -> Option<&coverageinfo::CrateCoverageContext<'ll, 'tcx>> {
self.coverage_cx.as_ref()
} }
pub(crate) fn create_used_variable_impl(&self, name: &'static CStr, values: &[&'ll Value]) { pub(crate) fn create_used_variable_impl(&self, name: &'static CStr, values: &[&'ll Value]) {

View file

@ -54,11 +54,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
add_unused_functions(cx); add_unused_functions(cx);
} }
let function_coverage_map = match cx.coverage_context() { let function_coverage_map = cx.coverage_cx().take_function_coverage_map();
Some(ctx) => ctx.take_function_coverage_map(),
None => return,
};
if function_coverage_map.is_empty() { if function_coverage_map.is_empty() {
// This module has no functions with coverage instrumentation // This module has no functions with coverage instrumentation
return; return;
@ -543,9 +539,5 @@ fn add_unused_function_coverage<'tcx>(
// zero, because none of its counters/expressions are marked as seen. // zero, because none of its counters/expressions are marked as seen.
let function_coverage = FunctionCoverageCollector::unused(instance, function_coverage_info); let function_coverage = FunctionCoverageCollector::unused(instance, function_coverage_info);
if let Some(coverage_context) = cx.coverage_context() { cx.coverage_cx().function_coverage_map.borrow_mut().insert(instance, function_coverage);
coverage_context.function_coverage_map.borrow_mut().insert(instance, function_coverage);
} else {
bug!("Could not get the `coverage_context`");
}
} }

View file

@ -7,7 +7,6 @@ use rustc_codegen_ssa::traits::{
}; };
use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_llvm::RustString; use rustc_llvm::RustString;
use rustc_middle::bug;
use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::mir::coverage::CoverageKind;
use rustc_middle::ty::Instance; use rustc_middle::ty::Instance;
use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::layout::HasTyCtxt;
@ -76,15 +75,11 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
/// `instrprof.increment()`. The `Value` is only created once per instance. /// `instrprof.increment()`. The `Value` is only created once per instance.
/// Multiple invocations with the same instance return the same `Value`. /// Multiple invocations with the same instance return the same `Value`.
fn get_pgo_func_name_var(&self, instance: Instance<'tcx>) -> &'ll llvm::Value { fn get_pgo_func_name_var(&self, instance: Instance<'tcx>) -> &'ll llvm::Value {
if let Some(coverage_context) = self.coverage_context() {
debug!("getting pgo_func_name_var for instance={:?}", instance); debug!("getting pgo_func_name_var for instance={:?}", instance);
let mut pgo_func_name_var_map = coverage_context.pgo_func_name_var_map.borrow_mut(); let mut pgo_func_name_var_map = self.coverage_cx().pgo_func_name_var_map.borrow_mut();
pgo_func_name_var_map pgo_func_name_var_map
.entry(instance) .entry(instance)
.or_insert_with(|| create_pgo_func_name_var(self, instance)) .or_insert_with(|| create_pgo_func_name_var(self, instance))
} else {
bug!("Could not get the `coverage_context`");
}
} }
} }
@ -118,11 +113,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
cond_bitmaps.push(cond_bitmap); cond_bitmaps.push(cond_bitmap);
} }
self.coverage_context() self.coverage_cx().mcdc_condition_bitmap_map.borrow_mut().insert(instance, cond_bitmaps);
.expect("always present when coverage is enabled")
.mcdc_condition_bitmap_map
.borrow_mut()
.insert(instance, cond_bitmaps);
} }
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
@ -143,8 +134,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
return; return;
}; };
let Some(coverage_context) = bx.coverage_context() else { return }; let mut coverage_map = bx.coverage_cx().function_coverage_map.borrow_mut();
let mut coverage_map = coverage_context.function_coverage_map.borrow_mut();
let func_coverage = coverage_map let func_coverage = coverage_map
.entry(instance) .entry(instance)
.or_insert_with(|| FunctionCoverageCollector::new(instance, function_coverage_info)); .or_insert_with(|| FunctionCoverageCollector::new(instance, function_coverage_info));
@ -186,7 +176,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
} }
CoverageKind::CondBitmapUpdate { index, decision_depth } => { CoverageKind::CondBitmapUpdate { index, decision_depth } => {
drop(coverage_map); drop(coverage_map);
let cond_bitmap = coverage_context let cond_bitmap = bx
.coverage_cx()
.try_get_mcdc_condition_bitmap(&instance, decision_depth) .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_index = bx.const_i32(index as i32); let cond_index = bx.const_i32(index as i32);
@ -194,7 +185,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
} }
CoverageKind::TestVectorBitmapUpdate { bitmap_idx, decision_depth } => { CoverageKind::TestVectorBitmapUpdate { bitmap_idx, decision_depth } => {
drop(coverage_map); drop(coverage_map);
let cond_bitmap = coverage_context let cond_bitmap = bx.coverage_cx()
.try_get_mcdc_condition_bitmap(&instance, decision_depth) .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");
assert!( assert!(