coverage: Add enums to accommodate other kinds of coverage mappings
This commit is contained in:
parent
c5932182ad
commit
124fff0777
9 changed files with 94 additions and 49 deletions
|
@ -1,4 +1,4 @@
|
||||||
use rustc_middle::mir::coverage::{CounterId, CovTerm, ExpressionId};
|
use rustc_middle::mir::coverage::{CodeRegion, CounterId, CovTerm, ExpressionId, MappingKind};
|
||||||
|
|
||||||
/// Must match the layout of `LLVMRustCounterKind`.
|
/// Must match the layout of `LLVMRustCounterKind`.
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
@ -149,6 +149,24 @@ pub struct CounterMappingRegion {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CounterMappingRegion {
|
impl CounterMappingRegion {
|
||||||
|
pub(crate) fn from_mapping(
|
||||||
|
mapping_kind: &MappingKind,
|
||||||
|
local_file_id: u32,
|
||||||
|
code_region: &CodeRegion,
|
||||||
|
) -> Self {
|
||||||
|
let &CodeRegion { file_name: _, start_line, start_col, end_line, end_col } = code_region;
|
||||||
|
match *mapping_kind {
|
||||||
|
MappingKind::Code(term) => Self::code_region(
|
||||||
|
Counter::from_term(term),
|
||||||
|
local_file_id,
|
||||||
|
start_line,
|
||||||
|
start_col,
|
||||||
|
end_line,
|
||||||
|
end_col,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn code_region(
|
pub(crate) fn code_region(
|
||||||
counter: Counter,
|
counter: Counter,
|
||||||
file_id: u32,
|
file_id: u32,
|
||||||
|
|
|
@ -4,7 +4,8 @@ use rustc_data_structures::captures::Captures;
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
use rustc_data_structures::fx::FxIndexSet;
|
||||||
use rustc_index::bit_set::BitSet;
|
use rustc_index::bit_set::BitSet;
|
||||||
use rustc_middle::mir::coverage::{
|
use rustc_middle::mir::coverage::{
|
||||||
CodeRegion, CounterId, CovTerm, Expression, ExpressionId, FunctionCoverageInfo, Mapping, Op,
|
CodeRegion, CounterId, CovTerm, Expression, ExpressionId, FunctionCoverageInfo, Mapping,
|
||||||
|
MappingKind, Op,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::Instance;
|
use rustc_middle::ty::Instance;
|
||||||
use rustc_span::Symbol;
|
use rustc_span::Symbol;
|
||||||
|
@ -64,8 +65,8 @@ impl<'tcx> FunctionCoverageCollector<'tcx> {
|
||||||
// For each expression ID that is directly used by one or more mappings,
|
// For each expression ID that is directly used by one or more mappings,
|
||||||
// mark it as not-yet-seen. This indicates that we expect to see a
|
// mark it as not-yet-seen. This indicates that we expect to see a
|
||||||
// corresponding `ExpressionUsed` statement during MIR traversal.
|
// corresponding `ExpressionUsed` statement during MIR traversal.
|
||||||
for Mapping { term, .. } in &function_coverage_info.mappings {
|
for term in function_coverage_info.mappings.iter().flat_map(|m| m.kind.terms()) {
|
||||||
if let &CovTerm::Expression(id) = term {
|
if let CovTerm::Expression(id) = term {
|
||||||
expressions_seen.remove(id);
|
expressions_seen.remove(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,20 +222,21 @@ impl<'tcx> FunctionCoverage<'tcx> {
|
||||||
/// that will be used by `mapgen` when preparing for FFI.
|
/// that will be used by `mapgen` when preparing for FFI.
|
||||||
pub(crate) fn counter_regions(
|
pub(crate) fn counter_regions(
|
||||||
&self,
|
&self,
|
||||||
) -> impl Iterator<Item = (Counter, &CodeRegion)> + ExactSizeIterator {
|
) -> impl Iterator<Item = (MappingKind, &CodeRegion)> + ExactSizeIterator {
|
||||||
self.function_coverage_info.mappings.iter().map(move |mapping| {
|
self.function_coverage_info.mappings.iter().map(move |mapping| {
|
||||||
let &Mapping { term, ref code_region } = mapping;
|
let Mapping { kind, code_region } = mapping;
|
||||||
let counter = self.counter_for_term(term);
|
let kind =
|
||||||
(counter, code_region)
|
kind.map_terms(|term| if self.is_zero_term(term) { CovTerm::Zero } else { term });
|
||||||
|
(kind, code_region)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn counter_for_term(&self, term: CovTerm) -> Counter {
|
fn counter_for_term(&self, term: CovTerm) -> Counter {
|
||||||
if is_zero_term(&self.counters_seen, &self.zero_expressions, term) {
|
if self.is_zero_term(term) { Counter::ZERO } else { Counter::from_term(term) }
|
||||||
Counter::ZERO
|
}
|
||||||
} else {
|
|
||||||
Counter::from_term(term)
|
fn is_zero_term(&self, term: CovTerm) -> bool {
|
||||||
}
|
is_zero_term(&self.counters_seen, &self.zero_expressions, term)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@ use rustc_hir::def_id::DefId;
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
use rustc_middle::mir::coverage::CodeRegion;
|
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_span::def_id::DefIdSet;
|
use rustc_span::def_id::DefIdSet;
|
||||||
use rustc_span::Symbol;
|
use rustc_span::Symbol;
|
||||||
|
@ -237,7 +236,7 @@ fn encode_mappings_for_function(
|
||||||
// Prepare file IDs for each filename, and prepare the mapping data so that
|
// Prepare file IDs for each filename, and prepare the mapping data so that
|
||||||
// we can pass it through FFI to LLVM.
|
// we can pass it through FFI to LLVM.
|
||||||
for (file_name, counter_regions_for_file) in
|
for (file_name, counter_regions_for_file) in
|
||||||
&counter_regions.group_by(|(_counter, region)| region.file_name)
|
&counter_regions.group_by(|(_, region)| region.file_name)
|
||||||
{
|
{
|
||||||
// Look up the global file ID for this filename.
|
// Look up the global file ID for this filename.
|
||||||
let global_file_id = global_file_table.global_file_id_for_file_name(file_name);
|
let global_file_id = global_file_table.global_file_id_for_file_name(file_name);
|
||||||
|
@ -248,17 +247,12 @@ fn encode_mappings_for_function(
|
||||||
|
|
||||||
// For each counter/region pair in this function+file, convert it to a
|
// For each counter/region pair in this function+file, convert it to a
|
||||||
// form suitable for FFI.
|
// form suitable for FFI.
|
||||||
for (counter, region) in counter_regions_for_file {
|
for (mapping_kind, region) in counter_regions_for_file {
|
||||||
let CodeRegion { file_name: _, start_line, start_col, end_line, end_col } = *region;
|
debug!("Adding counter {mapping_kind:?} to map for {region:?}");
|
||||||
|
mapping_regions.push(CounterMappingRegion::from_mapping(
|
||||||
debug!("Adding counter {counter:?} to map for {region:?}");
|
&mapping_kind,
|
||||||
mapping_regions.push(CounterMappingRegion::code_region(
|
|
||||||
counter,
|
|
||||||
local_file_id.as_u32(),
|
local_file_id.as_u32(),
|
||||||
start_line,
|
region,
|
||||||
start_col,
|
|
||||||
end_line,
|
|
||||||
end_col,
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,16 +160,34 @@ pub struct Expression {
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
|
#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
|
||||||
pub struct Mapping {
|
pub enum MappingKind {
|
||||||
pub code_region: CodeRegion,
|
/// Associates a normal region of code with a counter/expression/zero.
|
||||||
|
Code(CovTerm),
|
||||||
|
}
|
||||||
|
|
||||||
/// Indicates whether this mapping uses a counter value, expression value,
|
impl MappingKind {
|
||||||
/// or zero value.
|
/// Iterator over all coverage terms in this mapping kind.
|
||||||
///
|
pub fn terms(&self) -> impl Iterator<Item = CovTerm> {
|
||||||
/// FIXME: When we add support for mapping kinds other than `Code`
|
let one = |a| std::iter::once(a);
|
||||||
/// (e.g. branch regions, expansion regions), replace this with a dedicated
|
match *self {
|
||||||
/// mapping-kind enum.
|
Self::Code(term) => one(term),
|
||||||
pub term: CovTerm,
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a copy of this mapping kind, in which all coverage terms have
|
||||||
|
/// been replaced with ones returned by the given function.
|
||||||
|
pub fn map_terms(&self, map_fn: impl Fn(CovTerm) -> CovTerm) -> Self {
|
||||||
|
match *self {
|
||||||
|
Self::Code(term) => Self::Code(map_fn(term)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
|
||||||
|
pub struct Mapping {
|
||||||
|
pub kind: MappingKind,
|
||||||
|
pub code_region: CodeRegion,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stores per-function coverage information attached to a `mir::Body`,
|
/// Stores per-function coverage information attached to a `mir::Body`,
|
||||||
|
|
|
@ -493,8 +493,8 @@ fn write_function_coverage_info(
|
||||||
for (id, expression) in expressions.iter_enumerated() {
|
for (id, expression) in expressions.iter_enumerated() {
|
||||||
writeln!(w, "{INDENT}coverage {id:?} => {expression:?};")?;
|
writeln!(w, "{INDENT}coverage {id:?} => {expression:?};")?;
|
||||||
}
|
}
|
||||||
for coverage::Mapping { term, code_region } in mappings {
|
for coverage::Mapping { kind, code_region } in mappings {
|
||||||
writeln!(w, "{INDENT}coverage {term:?} => {code_region:?};")?;
|
writeln!(w, "{INDENT}coverage {kind:?} => {code_region:?};")?;
|
||||||
}
|
}
|
||||||
writeln!(w)?;
|
writeln!(w)?;
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ mod tests;
|
||||||
|
|
||||||
use self::counters::{BcbCounter, CoverageCounters};
|
use self::counters::{BcbCounter, CoverageCounters};
|
||||||
use self::graph::{BasicCoverageBlock, CoverageGraph};
|
use self::graph::{BasicCoverageBlock, CoverageGraph};
|
||||||
use self::spans::{BcbMapping, CoverageSpans};
|
use self::spans::{BcbMapping, BcbMappingKind, CoverageSpans};
|
||||||
|
|
||||||
use crate::MirPass;
|
use crate::MirPass;
|
||||||
|
|
||||||
|
@ -150,10 +150,12 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
|
||||||
|
|
||||||
coverage_spans
|
coverage_spans
|
||||||
.all_bcb_mappings()
|
.all_bcb_mappings()
|
||||||
.filter_map(|&BcbMapping { bcb, span }| {
|
.filter_map(|&BcbMapping { kind: bcb_mapping_kind, span }| {
|
||||||
let term = term_for_bcb(bcb);
|
let kind = match bcb_mapping_kind {
|
||||||
|
BcbMappingKind::Code(bcb) => MappingKind::Code(term_for_bcb(bcb)),
|
||||||
|
};
|
||||||
let code_region = make_code_region(source_map, file_name, span, body_span)?;
|
let code_region = make_code_region(source_map, file_name, span, body_span)?;
|
||||||
Some(Mapping { term, code_region })
|
Some(Mapping { kind, code_region })
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,15 @@ use crate::coverage::ExtractedHirInfo;
|
||||||
|
|
||||||
mod from_mir;
|
mod from_mir;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub(super) enum BcbMappingKind {
|
||||||
|
/// Associates an ordinary executable code span with its corresponding BCB.
|
||||||
|
Code(BasicCoverageBlock),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(super) struct BcbMapping {
|
pub(super) struct BcbMapping {
|
||||||
pub(super) bcb: BasicCoverageBlock,
|
pub(super) kind: BcbMappingKind,
|
||||||
pub(super) span: Span,
|
pub(super) span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +44,7 @@ impl CoverageSpans {
|
||||||
);
|
);
|
||||||
mappings.extend(coverage_spans.into_iter().map(|CoverageSpan { bcb, span, .. }| {
|
mappings.extend(coverage_spans.into_iter().map(|CoverageSpan { bcb, span, .. }| {
|
||||||
// Each span produced by the generator represents an ordinary code region.
|
// Each span produced by the generator represents an ordinary code region.
|
||||||
BcbMapping { bcb, span }
|
BcbMapping { kind: BcbMappingKind::Code(bcb), span }
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if mappings.is_empty() {
|
if mappings.is_empty() {
|
||||||
|
@ -47,8 +53,13 @@ impl CoverageSpans {
|
||||||
|
|
||||||
// Identify which BCBs have one or more mappings.
|
// Identify which BCBs have one or more mappings.
|
||||||
let mut bcb_has_mappings = BitSet::new_empty(basic_coverage_blocks.num_nodes());
|
let mut bcb_has_mappings = BitSet::new_empty(basic_coverage_blocks.num_nodes());
|
||||||
for &BcbMapping { bcb, span: _ } in &mappings {
|
let mut insert = |bcb| {
|
||||||
bcb_has_mappings.insert(bcb);
|
bcb_has_mappings.insert(bcb);
|
||||||
|
};
|
||||||
|
for &BcbMapping { kind, span: _ } in &mappings {
|
||||||
|
match kind {
|
||||||
|
BcbMappingKind::Code(bcb) => insert(bcb),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(Self { bcb_has_mappings, mappings })
|
Some(Self { bcb_has_mappings, mappings })
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
fn bar() -> bool {
|
fn bar() -> bool {
|
||||||
let mut _0: bool;
|
let mut _0: bool;
|
||||||
|
|
||||||
+ coverage Counter(0) => /the/src/instrument_coverage.rs:21:1 - 23:2;
|
+ coverage Code(Counter(0)) => /the/src/instrument_coverage.rs:21:1 - 23:2;
|
||||||
+
|
+
|
||||||
bb0: {
|
bb0: {
|
||||||
+ Coverage::CounterIncrement(0);
|
+ Coverage::CounterIncrement(0);
|
||||||
|
|
|
@ -9,11 +9,11 @@
|
||||||
|
|
||||||
+ coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Add, rhs: Counter(1) };
|
+ coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Add, rhs: Counter(1) };
|
||||||
+ coverage ExpressionId(1) => Expression { lhs: Expression(0), op: Subtract, rhs: Counter(1) };
|
+ coverage ExpressionId(1) => Expression { lhs: Expression(0), op: Subtract, rhs: Counter(1) };
|
||||||
+ coverage Counter(0) => /the/src/instrument_coverage.rs:12:1 - 12:11;
|
+ coverage Code(Counter(0)) => /the/src/instrument_coverage.rs:12:1 - 12:11;
|
||||||
+ coverage Expression(0) => /the/src/instrument_coverage.rs:13:5 - 14:17;
|
+ coverage Code(Expression(0)) => /the/src/instrument_coverage.rs:13:5 - 14:17;
|
||||||
+ coverage Expression(1) => /the/src/instrument_coverage.rs:15:13 - 15:18;
|
+ coverage Code(Expression(1)) => /the/src/instrument_coverage.rs:15:13 - 15:18;
|
||||||
+ coverage Expression(1) => /the/src/instrument_coverage.rs:18:1 - 18:2;
|
+ coverage Code(Counter(1)) => /the/src/instrument_coverage.rs:16:10 - 16:11;
|
||||||
+ coverage Counter(1) => /the/src/instrument_coverage.rs:16:10 - 16:11;
|
+ coverage Code(Expression(1)) => /the/src/instrument_coverage.rs:18:1 - 18:2;
|
||||||
+
|
+
|
||||||
bb0: {
|
bb0: {
|
||||||
+ Coverage::CounterIncrement(0);
|
+ Coverage::CounterIncrement(0);
|
||||||
|
|
Loading…
Add table
Reference in a new issue