coverage: Store extracted spans as a flat list of mappings
This is less elegant in some ways, since we no longer visit a BCB's spans as a batch, but will make it much easier to add support for other kinds of coverage mapping regions (e.g. branch regions or gap regions).
This commit is contained in:
parent
8f98b54a7e
commit
c5932182ad
2 changed files with 27 additions and 27 deletions
|
@ -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::CoverageSpans;
|
use self::spans::{BcbMapping, CoverageSpans};
|
||||||
|
|
||||||
use crate::MirPass;
|
use crate::MirPass;
|
||||||
|
|
||||||
|
@ -149,16 +149,9 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
coverage_spans
|
coverage_spans
|
||||||
.bcbs_with_coverage_spans()
|
.all_bcb_mappings()
|
||||||
// For each BCB with spans, get a coverage term for its counter.
|
.filter_map(|&BcbMapping { bcb, span }| {
|
||||||
.map(|(bcb, spans)| {
|
|
||||||
let term = term_for_bcb(bcb);
|
let term = term_for_bcb(bcb);
|
||||||
(term, spans)
|
|
||||||
})
|
|
||||||
// Flatten the spans into individual term/span pairs.
|
|
||||||
.flat_map(|(term, spans)| spans.iter().map(move |&span| (term, span)))
|
|
||||||
// Convert each span to a code region, and create the final mapping.
|
|
||||||
.filter_map(|(term, span)| {
|
|
||||||
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 { term, code_region })
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use rustc_data_structures::graph::WithNumNodes;
|
use rustc_data_structures::graph::WithNumNodes;
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::bit_set::BitSet;
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
use rustc_span::{BytePos, Span, DUMMY_SP};
|
use rustc_span::{BytePos, Span, DUMMY_SP};
|
||||||
|
|
||||||
|
@ -8,9 +8,15 @@ use crate::coverage::ExtractedHirInfo;
|
||||||
|
|
||||||
mod from_mir;
|
mod from_mir;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(super) struct BcbMapping {
|
||||||
|
pub(super) bcb: BasicCoverageBlock,
|
||||||
|
pub(super) span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) struct CoverageSpans {
|
pub(super) struct CoverageSpans {
|
||||||
/// Map from BCBs to their list of coverage spans.
|
bcb_has_mappings: BitSet<BasicCoverageBlock>,
|
||||||
bcb_to_spans: IndexVec<BasicCoverageBlock, Vec<Span>>,
|
mappings: Vec<BcbMapping>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CoverageSpans {
|
impl CoverageSpans {
|
||||||
|
@ -23,36 +29,37 @@ impl CoverageSpans {
|
||||||
hir_info: &ExtractedHirInfo,
|
hir_info: &ExtractedHirInfo,
|
||||||
basic_coverage_blocks: &CoverageGraph,
|
basic_coverage_blocks: &CoverageGraph,
|
||||||
) -> Option<Self> {
|
) -> Option<Self> {
|
||||||
|
let mut mappings = vec![];
|
||||||
|
|
||||||
let coverage_spans = CoverageSpansGenerator::generate_coverage_spans(
|
let coverage_spans = CoverageSpansGenerator::generate_coverage_spans(
|
||||||
mir_body,
|
mir_body,
|
||||||
hir_info,
|
hir_info,
|
||||||
basic_coverage_blocks,
|
basic_coverage_blocks,
|
||||||
);
|
);
|
||||||
|
mappings.extend(coverage_spans.into_iter().map(|CoverageSpan { bcb, span, .. }| {
|
||||||
|
// Each span produced by the generator represents an ordinary code region.
|
||||||
|
BcbMapping { bcb, span }
|
||||||
|
}));
|
||||||
|
|
||||||
if coverage_spans.is_empty() {
|
if mappings.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Group the coverage spans by BCB, with the BCBs in sorted order.
|
// Identify which BCBs have one or more mappings.
|
||||||
let mut bcb_to_spans = IndexVec::from_elem_n(Vec::new(), basic_coverage_blocks.num_nodes());
|
let mut bcb_has_mappings = BitSet::new_empty(basic_coverage_blocks.num_nodes());
|
||||||
for CoverageSpan { bcb, span, .. } in coverage_spans {
|
for &BcbMapping { bcb, span: _ } in &mappings {
|
||||||
bcb_to_spans[bcb].push(span);
|
bcb_has_mappings.insert(bcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(Self { bcb_to_spans })
|
Some(Self { bcb_has_mappings, mappings })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn bcb_has_coverage_spans(&self, bcb: BasicCoverageBlock) -> bool {
|
pub(super) fn bcb_has_coverage_spans(&self, bcb: BasicCoverageBlock) -> bool {
|
||||||
!self.bcb_to_spans[bcb].is_empty()
|
self.bcb_has_mappings.contains(bcb)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn bcbs_with_coverage_spans(
|
pub(super) fn all_bcb_mappings(&self) -> impl Iterator<Item = &BcbMapping> {
|
||||||
&self,
|
self.mappings.iter()
|
||||||
) -> impl Iterator<Item = (BasicCoverageBlock, &[Span])> {
|
|
||||||
self.bcb_to_spans.iter_enumerated().filter_map(|(bcb, spans)| {
|
|
||||||
// Only yield BCBs that have at least one coverage span.
|
|
||||||
(!spans.is_empty()).then_some((bcb, spans.as_slice()))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue