Skip to content

Commit 52d608b

Browse files
committed
coverage: Eagerly do start-of-function codegen for coverage
1 parent f705de5 commit 52d608b

File tree

3 files changed

+36
-27
lines changed

3 files changed

+36
-27
lines changed

compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs

+27-27
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_codegen_ssa::traits::{
1313
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
1414
use rustc_llvm::RustString;
1515
use rustc_middle::bug;
16-
use rustc_middle::mir::coverage::{CoverageKind, FunctionCoverageInfo};
16+
use rustc_middle::mir::coverage::CoverageKind;
1717
use rustc_middle::ty::layout::HasTyCtxt;
1818
use rustc_middle::ty::Instance;
1919
use rustc_target::abi::Align;
@@ -91,6 +91,32 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
9191
}
9292

9393
impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
94+
fn init_coverage(&mut self, instance: Instance<'tcx>) {
95+
let Some(function_coverage_info) =
96+
self.tcx.instance_mir(instance.def).function_coverage_info.as_deref()
97+
else {
98+
return;
99+
};
100+
101+
// If there are no MC/DC bitmaps to set up, return immediately.
102+
if function_coverage_info.mcdc_bitmap_bytes == 0 {
103+
return;
104+
}
105+
106+
let fn_name = self.get_pgo_func_name_var(instance);
107+
let hash = self.const_u64(function_coverage_info.function_source_hash);
108+
let bitmap_bytes = self.const_u32(function_coverage_info.mcdc_bitmap_bytes);
109+
let max_decision_depth = function_coverage_info.mcdc_max_decision_depth;
110+
let cond_bitmap =
111+
self.mcdc_parameters(fn_name, hash, bitmap_bytes, max_decision_depth as u32);
112+
113+
self.coverage_context()
114+
.expect("always present when coverage is enabled")
115+
.mcdc_condition_bitmap_map
116+
.borrow_mut()
117+
.insert(instance, cond_bitmap);
118+
}
119+
94120
#[instrument(level = "debug", skip(self))]
95121
fn add_coverage(&mut self, instance: Instance<'tcx>, kind: &CoverageKind) {
96122
// Our caller should have already taken care of inlining subtleties,
@@ -109,10 +135,6 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
109135
return;
110136
};
111137

112-
if function_coverage_info.mcdc_bitmap_bytes > 0 {
113-
ensure_mcdc_parameters(bx, instance, function_coverage_info);
114-
}
115-
116138
let Some(coverage_context) = bx.coverage_context() else { return };
117139
let mut coverage_map = coverage_context.function_coverage_map.borrow_mut();
118140
let func_coverage = coverage_map
@@ -193,28 +215,6 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
193215
}
194216
}
195217

196-
fn ensure_mcdc_parameters<'ll, 'tcx>(
197-
bx: &mut Builder<'_, 'll, 'tcx>,
198-
instance: Instance<'tcx>,
199-
function_coverage_info: &FunctionCoverageInfo,
200-
) {
201-
let Some(cx) = bx.coverage_context() else { return };
202-
if cx.mcdc_condition_bitmap_map.borrow().contains_key(&instance) {
203-
return;
204-
}
205-
206-
let fn_name = bx.get_pgo_func_name_var(instance);
207-
let hash = bx.const_u64(function_coverage_info.function_source_hash);
208-
let bitmap_bytes = bx.const_u32(function_coverage_info.mcdc_bitmap_bytes);
209-
let max_decision_depth = function_coverage_info.mcdc_max_decision_depth;
210-
let cond_bitmap = bx.mcdc_parameters(fn_name, hash, bitmap_bytes, max_decision_depth as u32);
211-
bx.coverage_context()
212-
.expect("already checked above")
213-
.mcdc_condition_bitmap_map
214-
.borrow_mut()
215-
.insert(instance, cond_bitmap);
216-
}
217-
218218
/// Calls llvm::createPGOFuncNameVar() with the given function instance's
219219
/// mangled function name. The LLVM API returns an llvm::GlobalVariable
220220
/// containing the function name, with the specific variable name and linkage

compiler/rustc_codegen_ssa/src/mir/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
259259
// Apply debuginfo to the newly allocated locals.
260260
fx.debug_introduce_locals(&mut start_bx);
261261

262+
// If the backend supports coverage, and coverage is enabled for this function,
263+
// do any necessary start-of-function codegen (e.g. locals for MC/DC bitmaps).
264+
start_bx.init_coverage(instance);
265+
262266
// The builders will be created separately for each basic block at `codegen_block`.
263267
// So drop the builder of `start_llbb` to avoid having two at the same time.
264268
drop(start_bx);

compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ use rustc_middle::mir::coverage::CoverageKind;
33
use rustc_middle::ty::Instance;
44

55
pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes {
6+
/// Performs any start-of-function codegen needed for coverage instrumentation.
7+
///
8+
/// Can be a no-op in backends that don't support coverage instrumentation.
9+
fn init_coverage(&mut self, _instance: Instance<'tcx>) {}
10+
611
/// Handle the MIR coverage info in a backend-specific way.
712
///
813
/// This can potentially be a no-op in backends that don't support

0 commit comments

Comments
 (0)