Skip to content

Commit d4f1062

Browse files
committed
coverage: Pull expression conversion out of map_data.rs
1 parent f824c15 commit d4f1062

File tree

2 files changed

+44
-33
lines changed

2 files changed

+44
-33
lines changed

compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs

+1-31
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
1-
use rustc_data_structures::captures::Captures;
21
use rustc_middle::mir::coverage::{
3-
CovTerm, CoverageIdsInfo, Expression, FunctionCoverageInfo, Mapping, MappingKind, Op,
4-
SourceRegion,
2+
CovTerm, CoverageIdsInfo, FunctionCoverageInfo, Mapping, MappingKind, SourceRegion,
53
};
64

7-
use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind};
8-
95
pub(crate) struct FunctionCoverage<'tcx> {
106
pub(crate) function_coverage_info: &'tcx FunctionCoverageInfo,
117
/// If `None`, the corresponding function is unused.
@@ -35,28 +31,6 @@ impl<'tcx> FunctionCoverage<'tcx> {
3531
if self.is_used() { self.function_coverage_info.function_source_hash } else { 0 }
3632
}
3733

38-
/// Convert this function's coverage expression data into a form that can be
39-
/// passed through FFI to LLVM.
40-
pub(crate) fn counter_expressions(
41-
&self,
42-
) -> impl Iterator<Item = CounterExpression> + ExactSizeIterator + Captures<'_> {
43-
// We know that LLVM will optimize out any unused expressions before
44-
// producing the final coverage map, so there's no need to do the same
45-
// thing on the Rust side unless we're confident we can do much better.
46-
// (See `CounterExpressionsMinimizer` in `CoverageMappingWriter.cpp`.)
47-
48-
self.function_coverage_info.expressions.iter().map(move |&Expression { lhs, op, rhs }| {
49-
CounterExpression {
50-
lhs: self.counter_for_term(lhs),
51-
kind: match op {
52-
Op::Add => ExprKind::Add,
53-
Op::Subtract => ExprKind::Subtract,
54-
},
55-
rhs: self.counter_for_term(rhs),
56-
}
57-
})
58-
}
59-
6034
/// Converts this function's coverage mappings into an intermediate form
6135
/// that will be used by `mapgen` when preparing for FFI.
6236
pub(crate) fn counter_regions(
@@ -70,10 +44,6 @@ impl<'tcx> FunctionCoverage<'tcx> {
7044
})
7145
}
7246

73-
fn counter_for_term(&self, term: CovTerm) -> Counter {
74-
if self.is_zero_term(term) { Counter::ZERO } else { Counter::from_term(term) }
75-
}
76-
7747
fn is_zero_term(&self, term: CovTerm) -> bool {
7848
match self.ids_info {
7949
Some(ids_info) => ids_info.is_zero_term(term),

compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs

+43-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ use rustc_codegen_ssa::traits::{
1111
BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods,
1212
};
1313
use rustc_middle::bug;
14-
use rustc_middle::mir::coverage::MappingKind;
14+
use rustc_middle::mir::coverage::{
15+
CoverageIdsInfo, Expression, FunctionCoverageInfo, MappingKind, Op,
16+
};
1517
use rustc_middle::ty::{Instance, TyCtxt};
1618
use rustc_target::spec::HasTargetSpec;
1719
use tracing::debug;
@@ -49,12 +51,17 @@ pub(crate) fn prepare_covfun_record<'tcx>(
4951
instance: Instance<'tcx>,
5052
function_coverage: &FunctionCoverage<'tcx>,
5153
) -> Option<CovfunRecord<'tcx>> {
54+
let fn_cov_info = tcx.instance_mir(instance.def).function_coverage_info.as_deref()?;
55+
let ids_info = tcx.coverage_ids_info(instance.def);
56+
57+
let expressions = prepare_expressions(fn_cov_info, ids_info, function_coverage.is_used());
58+
5259
let mut covfun = CovfunRecord {
5360
mangled_function_name: tcx.symbol_name(instance).name,
5461
source_hash: function_coverage.source_hash(),
5562
is_used: function_coverage.is_used(),
5663
virtual_file_mapping: VirtualFileMapping::default(),
57-
expressions: function_coverage.counter_expressions().collect::<Vec<_>>(),
64+
expressions,
5865
regions: ffi::Regions::default(),
5966
};
6067

@@ -72,6 +79,40 @@ pub(crate) fn prepare_covfun_record<'tcx>(
7279
Some(covfun)
7380
}
7481

82+
/// Convert the function's coverage-counter expressions into a form suitable for FFI.
83+
fn prepare_expressions(
84+
fn_cov_info: &FunctionCoverageInfo,
85+
ids_info: &CoverageIdsInfo,
86+
is_used: bool,
87+
) -> Vec<ffi::CounterExpression> {
88+
// If any counters or expressions were removed by MIR opts, replace their
89+
// terms with zero.
90+
let counter_for_term = |term| {
91+
if !is_used || ids_info.is_zero_term(term) {
92+
ffi::Counter::ZERO
93+
} else {
94+
ffi::Counter::from_term(term)
95+
}
96+
};
97+
98+
// We know that LLVM will optimize out any unused expressions before
99+
// producing the final coverage map, so there's no need to do the same
100+
// thing on the Rust side unless we're confident we can do much better.
101+
// (See `CounterExpressionsMinimizer` in `CoverageMappingWriter.cpp`.)
102+
fn_cov_info
103+
.expressions
104+
.iter()
105+
.map(move |&Expression { lhs, op, rhs }| ffi::CounterExpression {
106+
lhs: counter_for_term(lhs),
107+
kind: match op {
108+
Op::Add => ffi::ExprKind::Add,
109+
Op::Subtract => ffi::ExprKind::Subtract,
110+
},
111+
rhs: counter_for_term(rhs),
112+
})
113+
.collect::<Vec<_>>()
114+
}
115+
75116
/// Populates the mapping region tables in the current function's covfun record.
76117
fn fill_region_tables<'tcx>(
77118
tcx: TyCtxt<'tcx>,

0 commit comments

Comments
 (0)