coverage: Encapsulate coverage spans
By encapsulating the coverage spans in a struct, we can change the internal representation without disturbing existing call sites. This will be useful for grouping coverage spans by BCB. This patch includes some changes that were originally in #115912, which avoid the need for a particular test to deal with coverage spans at all. (Comments/logs referring to `CoverageSpan` are updated in a subsequent patch.)
This commit is contained in:
parent
59a11af1f9
commit
e29db47176
4 changed files with 63 additions and 54 deletions
|
@ -1,6 +1,7 @@
|
|||
use super::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB};
|
||||
|
||||
use rustc_data_structures::graph::WithNumNodes;
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_middle::mir::{
|
||||
self, AggregateKind, BasicBlock, FakeReadCause, Rvalue, Statement, StatementKind, Terminator,
|
||||
TerminatorKind,
|
||||
|
@ -10,6 +11,42 @@ use rustc_span::{BytePos, ExpnKind, MacroKind, Span, Symbol};
|
|||
|
||||
use std::cell::OnceCell;
|
||||
|
||||
pub(super) struct CoverageSpans {
|
||||
coverage_spans: Vec<CoverageSpan>,
|
||||
bcbs_with_coverage_spans: BitSet<BasicCoverageBlock>,
|
||||
}
|
||||
|
||||
impl CoverageSpans {
|
||||
pub(super) fn generate_coverage_spans(
|
||||
mir_body: &mir::Body<'_>,
|
||||
fn_sig_span: Span,
|
||||
body_span: Span,
|
||||
basic_coverage_blocks: &CoverageGraph,
|
||||
) -> Self {
|
||||
let coverage_spans = CoverageSpansGenerator::generate_coverage_spans(
|
||||
mir_body,
|
||||
fn_sig_span,
|
||||
body_span,
|
||||
basic_coverage_blocks,
|
||||
);
|
||||
|
||||
let mut bcbs_with_coverage_spans = BitSet::new_empty(basic_coverage_blocks.num_nodes());
|
||||
for coverage_span in &coverage_spans {
|
||||
bcbs_with_coverage_spans.insert(coverage_span.bcb);
|
||||
}
|
||||
|
||||
Self { coverage_spans, bcbs_with_coverage_spans }
|
||||
}
|
||||
|
||||
pub(super) fn bcb_has_coverage_spans(&self, bcb: BasicCoverageBlock) -> bool {
|
||||
self.bcbs_with_coverage_spans.contains(bcb)
|
||||
}
|
||||
|
||||
pub(super) fn bcb_span_pairs(&self) -> impl Iterator<Item = (BasicCoverageBlock, Span)> + '_ {
|
||||
self.coverage_spans.iter().map(|&CoverageSpan { bcb, span, .. }| (bcb, span))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub(super) enum CoverageStatement {
|
||||
Statement(BasicBlock, Span, usize),
|
||||
|
@ -35,7 +72,7 @@ impl CoverageStatement {
|
|||
/// or is subsumed by the `Span` associated with this `CoverageSpan`, and it's `BasicBlock`
|
||||
/// `dominates()` the `BasicBlock`s in this `CoverageSpan`.
|
||||
#[derive(Debug, Clone)]
|
||||
pub(super) struct CoverageSpan {
|
||||
struct CoverageSpan {
|
||||
pub span: Span,
|
||||
pub expn_span: Span,
|
||||
pub current_macro_or_none: OnceCell<Option<Symbol>>,
|
||||
|
@ -162,7 +199,7 @@ impl CoverageSpan {
|
|||
/// * Merge spans that represent continuous (both in source code and control flow), non-branching
|
||||
/// execution
|
||||
/// * Carve out (leave uncovered) any span that will be counted by another MIR (notably, closures)
|
||||
pub struct CoverageSpans<'a, 'tcx> {
|
||||
struct CoverageSpansGenerator<'a, 'tcx> {
|
||||
/// The MIR, used to look up `BasicBlockData`.
|
||||
mir_body: &'a mir::Body<'tcx>,
|
||||
|
||||
|
@ -218,7 +255,7 @@ pub struct CoverageSpans<'a, 'tcx> {
|
|||
refined_spans: Vec<CoverageSpan>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
|
||||
impl<'a, 'tcx> CoverageSpansGenerator<'a, 'tcx> {
|
||||
/// Generate a minimal set of `CoverageSpan`s, each representing a contiguous code region to be
|
||||
/// counted.
|
||||
///
|
||||
|
@ -246,7 +283,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
|
|||
body_span: Span,
|
||||
basic_coverage_blocks: &'a CoverageGraph,
|
||||
) -> Vec<CoverageSpan> {
|
||||
let mut coverage_spans = CoverageSpans {
|
||||
let mut coverage_spans = Self {
|
||||
mir_body,
|
||||
fn_sig_span,
|
||||
body_span,
|
||||
|
@ -734,7 +771,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
|
|||
|
||||
/// If the MIR `Statement` has a span contributive to computing coverage spans,
|
||||
/// return it; otherwise return `None`.
|
||||
pub(super) fn filtered_statement_span(statement: &Statement<'_>) -> Option<Span> {
|
||||
fn filtered_statement_span(statement: &Statement<'_>) -> Option<Span> {
|
||||
match statement.kind {
|
||||
// These statements have spans that are often outside the scope of the executed source code
|
||||
// for their parent `BasicBlock`.
|
||||
|
@ -781,7 +818,7 @@ pub(super) fn filtered_statement_span(statement: &Statement<'_>) -> Option<Span>
|
|||
|
||||
/// If the MIR `Terminator` has a span contributive to computing coverage spans,
|
||||
/// return it; otherwise return `None`.
|
||||
pub(super) fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Span> {
|
||||
fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Span> {
|
||||
match terminator.kind {
|
||||
// These terminators have spans that don't positively contribute to computing a reasonable
|
||||
// span of actually executed source code. (For example, SwitchInt terminators extracted from
|
||||
|
@ -828,7 +865,7 @@ pub(super) fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Sp
|
|||
/// [^1]Expansions result from Rust syntax including macros, syntactic sugar,
|
||||
/// etc.).
|
||||
#[inline]
|
||||
pub(super) fn function_source_span(span: Span, body_span: Span) -> Span {
|
||||
fn function_source_span(span: Span, body_span: Span) -> Span {
|
||||
let original_span = original_sp(span, body_span).with_ctxt(body_span.ctxt());
|
||||
if body_span.contains(original_span) { original_span } else { body_span }
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue