Skip to content

Commit 124fff0

Browse files
committed
coverage: Add enums to accommodate other kinds of coverage mappings
1 parent c593218 commit 124fff0

File tree

9 files changed

+93
-48
lines changed

9 files changed

+93
-48
lines changed

compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_middle::mir::coverage::{CounterId, CovTerm, ExpressionId};
1+
use rustc_middle::mir::coverage::{CodeRegion, CounterId, CovTerm, ExpressionId, MappingKind};
22

33
/// Must match the layout of `LLVMRustCounterKind`.
44
#[derive(Copy, Clone, Debug)]
@@ -149,6 +149,24 @@ pub struct CounterMappingRegion {
149149
}
150150

151151
impl CounterMappingRegion {
152+
pub(crate) fn from_mapping(
153+
mapping_kind: &MappingKind,
154+
local_file_id: u32,
155+
code_region: &CodeRegion,
156+
) -> Self {
157+
let &CodeRegion { file_name: _, start_line, start_col, end_line, end_col } = code_region;
158+
match *mapping_kind {
159+
MappingKind::Code(term) => Self::code_region(
160+
Counter::from_term(term),
161+
local_file_id,
162+
start_line,
163+
start_col,
164+
end_line,
165+
end_col,
166+
),
167+
}
168+
}
169+
152170
pub(crate) fn code_region(
153171
counter: Counter,
154172
file_id: u32,

compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs

+14-12
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ use rustc_data_structures::captures::Captures;
44
use rustc_data_structures::fx::FxIndexSet;
55
use rustc_index::bit_set::BitSet;
66
use rustc_middle::mir::coverage::{
7-
CodeRegion, CounterId, CovTerm, Expression, ExpressionId, FunctionCoverageInfo, Mapping, Op,
7+
CodeRegion, CounterId, CovTerm, Expression, ExpressionId, FunctionCoverageInfo, Mapping,
8+
MappingKind, Op,
89
};
910
use rustc_middle::ty::Instance;
1011
use rustc_span::Symbol;
@@ -64,8 +65,8 @@ impl<'tcx> FunctionCoverageCollector<'tcx> {
6465
// For each expression ID that is directly used by one or more mappings,
6566
// mark it as not-yet-seen. This indicates that we expect to see a
6667
// corresponding `ExpressionUsed` statement during MIR traversal.
67-
for Mapping { term, .. } in &function_coverage_info.mappings {
68-
if let &CovTerm::Expression(id) = term {
68+
for term in function_coverage_info.mappings.iter().flat_map(|m| m.kind.terms()) {
69+
if let CovTerm::Expression(id) = term {
6970
expressions_seen.remove(id);
7071
}
7172
}
@@ -221,20 +222,21 @@ impl<'tcx> FunctionCoverage<'tcx> {
221222
/// that will be used by `mapgen` when preparing for FFI.
222223
pub(crate) fn counter_regions(
223224
&self,
224-
) -> impl Iterator<Item = (Counter, &CodeRegion)> + ExactSizeIterator {
225+
) -> impl Iterator<Item = (MappingKind, &CodeRegion)> + ExactSizeIterator {
225226
self.function_coverage_info.mappings.iter().map(move |mapping| {
226-
let &Mapping { term, ref code_region } = mapping;
227-
let counter = self.counter_for_term(term);
228-
(counter, code_region)
227+
let Mapping { kind, code_region } = mapping;
228+
let kind =
229+
kind.map_terms(|term| if self.is_zero_term(term) { CovTerm::Zero } else { term });
230+
(kind, code_region)
229231
})
230232
}
231233

232234
fn counter_for_term(&self, term: CovTerm) -> Counter {
233-
if is_zero_term(&self.counters_seen, &self.zero_expressions, term) {
234-
Counter::ZERO
235-
} else {
236-
Counter::from_term(term)
237-
}
235+
if self.is_zero_term(term) { Counter::ZERO } else { Counter::from_term(term) }
236+
}
237+
238+
fn is_zero_term(&self, term: CovTerm) -> bool {
239+
is_zero_term(&self.counters_seen, &self.zero_expressions, term)
238240
}
239241
}
240242

compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs

+6-12
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use rustc_hir::def_id::DefId;
1212
use rustc_index::IndexVec;
1313
use rustc_middle::bug;
1414
use rustc_middle::mir;
15-
use rustc_middle::mir::coverage::CodeRegion;
1615
use rustc_middle::ty::{self, TyCtxt};
1716
use rustc_span::def_id::DefIdSet;
1817
use rustc_span::Symbol;
@@ -237,7 +236,7 @@ fn encode_mappings_for_function(
237236
// Prepare file IDs for each filename, and prepare the mapping data so that
238237
// we can pass it through FFI to LLVM.
239238
for (file_name, counter_regions_for_file) in
240-
&counter_regions.group_by(|(_counter, region)| region.file_name)
239+
&counter_regions.group_by(|(_, region)| region.file_name)
241240
{
242241
// Look up the global file ID for this filename.
243242
let global_file_id = global_file_table.global_file_id_for_file_name(file_name);
@@ -248,17 +247,12 @@ fn encode_mappings_for_function(
248247

249248
// For each counter/region pair in this function+file, convert it to a
250249
// form suitable for FFI.
251-
for (counter, region) in counter_regions_for_file {
252-
let CodeRegion { file_name: _, start_line, start_col, end_line, end_col } = *region;
253-
254-
debug!("Adding counter {counter:?} to map for {region:?}");
255-
mapping_regions.push(CounterMappingRegion::code_region(
256-
counter,
250+
for (mapping_kind, region) in counter_regions_for_file {
251+
debug!("Adding counter {mapping_kind:?} to map for {region:?}");
252+
mapping_regions.push(CounterMappingRegion::from_mapping(
253+
&mapping_kind,
257254
local_file_id.as_u32(),
258-
start_line,
259-
start_col,
260-
end_line,
261-
end_col,
255+
region,
262256
));
263257
}
264258
}

compiler/rustc_middle/src/mir/coverage.rs

+26-8
Original file line numberDiff line numberDiff line change
@@ -158,18 +158,36 @@ pub struct Expression {
158158
pub rhs: CovTerm,
159159
}
160160

161+
#[derive(Clone, Debug)]
162+
#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
163+
pub enum MappingKind {
164+
/// Associates a normal region of code with a counter/expression/zero.
165+
Code(CovTerm),
166+
}
167+
168+
impl MappingKind {
169+
/// Iterator over all coverage terms in this mapping kind.
170+
pub fn terms(&self) -> impl Iterator<Item = CovTerm> {
171+
let one = |a| std::iter::once(a);
172+
match *self {
173+
Self::Code(term) => one(term),
174+
}
175+
}
176+
177+
/// Returns a copy of this mapping kind, in which all coverage terms have
178+
/// been replaced with ones returned by the given function.
179+
pub fn map_terms(&self, map_fn: impl Fn(CovTerm) -> CovTerm) -> Self {
180+
match *self {
181+
Self::Code(term) => Self::Code(map_fn(term)),
182+
}
183+
}
184+
}
185+
161186
#[derive(Clone, Debug)]
162187
#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
163188
pub struct Mapping {
189+
pub kind: MappingKind,
164190
pub code_region: CodeRegion,
165-
166-
/// Indicates whether this mapping uses a counter value, expression value,
167-
/// or zero value.
168-
///
169-
/// FIXME: When we add support for mapping kinds other than `Code`
170-
/// (e.g. branch regions, expansion regions), replace this with a dedicated
171-
/// mapping-kind enum.
172-
pub term: CovTerm,
173191
}
174192

175193
/// Stores per-function coverage information attached to a `mir::Body`,

compiler/rustc_middle/src/mir/pretty.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -493,8 +493,8 @@ fn write_function_coverage_info(
493493
for (id, expression) in expressions.iter_enumerated() {
494494
writeln!(w, "{INDENT}coverage {id:?} => {expression:?};")?;
495495
}
496-
for coverage::Mapping { term, code_region } in mappings {
497-
writeln!(w, "{INDENT}coverage {term:?} => {code_region:?};")?;
496+
for coverage::Mapping { kind, code_region } in mappings {
497+
writeln!(w, "{INDENT}coverage {kind:?} => {code_region:?};")?;
498498
}
499499
writeln!(w)?;
500500

compiler/rustc_mir_transform/src/coverage/mod.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ mod tests;
99

1010
use self::counters::{BcbCounter, CoverageCounters};
1111
use self::graph::{BasicCoverageBlock, CoverageGraph};
12-
use self::spans::{BcbMapping, CoverageSpans};
12+
use self::spans::{BcbMapping, BcbMappingKind, CoverageSpans};
1313

1414
use crate::MirPass;
1515

@@ -150,10 +150,12 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
150150

151151
coverage_spans
152152
.all_bcb_mappings()
153-
.filter_map(|&BcbMapping { bcb, span }| {
154-
let term = term_for_bcb(bcb);
153+
.filter_map(|&BcbMapping { kind: bcb_mapping_kind, span }| {
154+
let kind = match bcb_mapping_kind {
155+
BcbMappingKind::Code(bcb) => MappingKind::Code(term_for_bcb(bcb)),
156+
};
155157
let code_region = make_code_region(source_map, file_name, span, body_span)?;
156-
Some(Mapping { term, code_region })
158+
Some(Mapping { kind, code_region })
157159
})
158160
.collect::<Vec<_>>()
159161
}

compiler/rustc_mir_transform/src/coverage/spans.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,15 @@ use crate::coverage::ExtractedHirInfo;
88

99
mod from_mir;
1010

11+
#[derive(Clone, Copy, Debug)]
12+
pub(super) enum BcbMappingKind {
13+
/// Associates an ordinary executable code span with its corresponding BCB.
14+
Code(BasicCoverageBlock),
15+
}
16+
1117
#[derive(Debug)]
1218
pub(super) struct BcbMapping {
13-
pub(super) bcb: BasicCoverageBlock,
19+
pub(super) kind: BcbMappingKind,
1420
pub(super) span: Span,
1521
}
1622

@@ -38,7 +44,7 @@ impl CoverageSpans {
3844
);
3945
mappings.extend(coverage_spans.into_iter().map(|CoverageSpan { bcb, span, .. }| {
4046
// Each span produced by the generator represents an ordinary code region.
41-
BcbMapping { bcb, span }
47+
BcbMapping { kind: BcbMappingKind::Code(bcb), span }
4248
}));
4349

4450
if mappings.is_empty() {
@@ -47,8 +53,13 @@ impl CoverageSpans {
4753

4854
// Identify which BCBs have one or more mappings.
4955
let mut bcb_has_mappings = BitSet::new_empty(basic_coverage_blocks.num_nodes());
50-
for &BcbMapping { bcb, span: _ } in &mappings {
56+
let mut insert = |bcb| {
5157
bcb_has_mappings.insert(bcb);
58+
};
59+
for &BcbMapping { kind, span: _ } in &mappings {
60+
match kind {
61+
BcbMappingKind::Code(bcb) => insert(bcb),
62+
}
5263
}
5364

5465
Some(Self { bcb_has_mappings, mappings })

tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
fn bar() -> bool {
55
let mut _0: bool;
66

7-
+ coverage Counter(0) => /the/src/instrument_coverage.rs:21:1 - 23:2;
7+
+ coverage Code(Counter(0)) => /the/src/instrument_coverage.rs:21:1 - 23:2;
88
+
99
bb0: {
1010
+ Coverage::CounterIncrement(0);

tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff

+5-5
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@
99

1010
+ coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Add, rhs: Counter(1) };
1111
+ coverage ExpressionId(1) => Expression { lhs: Expression(0), op: Subtract, rhs: Counter(1) };
12-
+ coverage Counter(0) => /the/src/instrument_coverage.rs:12:1 - 12:11;
13-
+ coverage Expression(0) => /the/src/instrument_coverage.rs:13:5 - 14:17;
14-
+ coverage Expression(1) => /the/src/instrument_coverage.rs:15:13 - 15:18;
15-
+ coverage Expression(1) => /the/src/instrument_coverage.rs:18:1 - 18:2;
16-
+ coverage Counter(1) => /the/src/instrument_coverage.rs:16:10 - 16:11;
12+
+ coverage Code(Counter(0)) => /the/src/instrument_coverage.rs:12:1 - 12:11;
13+
+ coverage Code(Expression(0)) => /the/src/instrument_coverage.rs:13:5 - 14:17;
14+
+ coverage Code(Expression(1)) => /the/src/instrument_coverage.rs:15:13 - 15:18;
15+
+ coverage Code(Counter(1)) => /the/src/instrument_coverage.rs:16:10 - 16:11;
16+
+ coverage Code(Expression(1)) => /the/src/instrument_coverage.rs:18:1 - 18:2;
1717
+
1818
bb0: {
1919
+ Coverage::CounterIncrement(0);

0 commit comments

Comments
 (0)