Skip to content

Commit 972ab88

Browse files
committed
coverage: Move initial MIR span extraction into a submodule
1 parent fa6d1e7 commit 972ab88

File tree

2 files changed

+194
-185
lines changed

2 files changed

+194
-185
lines changed

compiler/rustc_mir_transform/src/coverage/spans.rs

+5-185
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
1-
use super::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB};
1+
use std::cell::OnceCell;
22

33
use rustc_data_structures::graph::WithNumNodes;
44
use rustc_index::IndexVec;
5-
use rustc_middle::mir::{
6-
self, AggregateKind, BasicBlock, FakeReadCause, Rvalue, Statement, StatementKind, Terminator,
7-
TerminatorKind,
8-
};
9-
use rustc_span::source_map::original_sp;
5+
use rustc_middle::mir::{self, AggregateKind, BasicBlock, Rvalue, Statement, StatementKind};
106
use rustc_span::{BytePos, ExpnKind, MacroKind, Span, Symbol};
117

12-
use std::cell::OnceCell;
8+
use super::graph::{BasicCoverageBlock, CoverageGraph, START_BCB};
9+
10+
mod from_mir;
1311

1412
pub(super) struct CoverageSpans {
1513
/// Map from BCBs to their list of coverage spans.
@@ -311,41 +309,6 @@ impl<'a, 'tcx> CoverageSpansGenerator<'a, 'tcx> {
311309
coverage_spans.to_refined_spans()
312310
}
313311

314-
fn mir_to_initial_sorted_coverage_spans(&self) -> Vec<CoverageSpan> {
315-
let mut initial_spans =
316-
Vec::<CoverageSpan>::with_capacity(self.mir_body.basic_blocks.len() * 2);
317-
for (bcb, bcb_data) in self.basic_coverage_blocks.iter_enumerated() {
318-
initial_spans.extend(self.bcb_to_initial_coverage_spans(bcb, bcb_data));
319-
}
320-
321-
if initial_spans.is_empty() {
322-
// This can happen if, for example, the function is unreachable (contains only a
323-
// `BasicBlock`(s) with an `Unreachable` terminator).
324-
return initial_spans;
325-
}
326-
327-
initial_spans.push(CoverageSpan::for_fn_sig(self.fn_sig_span));
328-
329-
initial_spans.sort_by(|a, b| {
330-
// First sort by span start.
331-
Ord::cmp(&a.span.lo(), &b.span.lo())
332-
// If span starts are the same, sort by span end in reverse order.
333-
// This ensures that if spans A and B are adjacent in the list,
334-
// and they overlap but are not equal, then either:
335-
// - Span A extends further left, or
336-
// - Both have the same start and span A extends further right
337-
.then_with(|| Ord::cmp(&a.span.hi(), &b.span.hi()).reverse())
338-
// If both spans are equal, sort the BCBs in dominator order,
339-
// so that dominating BCBs come before other BCBs they dominate.
340-
.then_with(|| self.basic_coverage_blocks.cmp_in_dominator_order(a.bcb, b.bcb))
341-
// If two spans are otherwise identical, put closure spans first,
342-
// as this seems to be what the refinement step expects.
343-
.then_with(|| Ord::cmp(&a.is_closure, &b.is_closure).reverse())
344-
});
345-
346-
initial_spans
347-
}
348-
349312
/// Iterate through the sorted `CoverageSpan`s, and return the refined list of merged and
350313
/// de-duplicated `CoverageSpan`s.
351314
fn to_refined_spans(mut self) -> Vec<CoverageSpan> {
@@ -485,48 +448,6 @@ impl<'a, 'tcx> CoverageSpansGenerator<'a, 'tcx> {
485448
}
486449
}
487450

488-
// Generate a set of `CoverageSpan`s from the filtered set of `Statement`s and `Terminator`s of
489-
// the `BasicBlock`(s) in the given `BasicCoverageBlockData`. One `CoverageSpan` is generated
490-
// for each `Statement` and `Terminator`. (Note that subsequent stages of coverage analysis will
491-
// merge some `CoverageSpan`s, at which point a `CoverageSpan` may represent multiple
492-
// `Statement`s and/or `Terminator`s.)
493-
fn bcb_to_initial_coverage_spans(
494-
&self,
495-
bcb: BasicCoverageBlock,
496-
bcb_data: &'a BasicCoverageBlockData,
497-
) -> Vec<CoverageSpan> {
498-
bcb_data
499-
.basic_blocks
500-
.iter()
501-
.flat_map(|&bb| {
502-
let data = &self.mir_body[bb];
503-
data.statements
504-
.iter()
505-
.enumerate()
506-
.filter_map(move |(index, statement)| {
507-
filtered_statement_span(statement).map(|span| {
508-
CoverageSpan::for_statement(
509-
statement,
510-
function_source_span(span, self.body_span),
511-
span,
512-
bcb,
513-
bb,
514-
index,
515-
)
516-
})
517-
})
518-
.chain(filtered_terminator_span(data.terminator()).map(|span| {
519-
CoverageSpan::for_terminator(
520-
function_source_span(span, self.body_span),
521-
span,
522-
bcb,
523-
bb,
524-
)
525-
}))
526-
})
527-
.collect()
528-
}
529-
530451
fn curr(&self) -> &CoverageSpan {
531452
self.some_curr
532453
.as_ref()
@@ -774,104 +695,3 @@ impl<'a, 'tcx> CoverageSpansGenerator<'a, 'tcx> {
774695
self.basic_coverage_blocks.dominates(dom_covspan.bcb, covspan.bcb)
775696
}
776697
}
777-
778-
/// If the MIR `Statement` has a span contributive to computing coverage spans,
779-
/// return it; otherwise return `None`.
780-
fn filtered_statement_span(statement: &Statement<'_>) -> Option<Span> {
781-
match statement.kind {
782-
// These statements have spans that are often outside the scope of the executed source code
783-
// for their parent `BasicBlock`.
784-
StatementKind::StorageLive(_)
785-
| StatementKind::StorageDead(_)
786-
// Coverage should not be encountered, but don't inject coverage coverage
787-
| StatementKind::Coverage(_)
788-
// Ignore `ConstEvalCounter`s
789-
| StatementKind::ConstEvalCounter
790-
// Ignore `Nop`s
791-
| StatementKind::Nop => None,
792-
793-
// FIXME(#78546): MIR InstrumentCoverage - Can the source_info.span for `FakeRead`
794-
// statements be more consistent?
795-
//
796-
// FakeReadCause::ForGuardBinding, in this example:
797-
// match somenum {
798-
// x if x < 1 => { ... }
799-
// }...
800-
// The BasicBlock within the match arm code included one of these statements, but the span
801-
// for it covered the `1` in this source. The actual statements have nothing to do with that
802-
// source span:
803-
// FakeRead(ForGuardBinding, _4);
804-
// where `_4` is:
805-
// _4 = &_1; (at the span for the first `x`)
806-
// and `_1` is the `Place` for `somenum`.
807-
//
808-
// If and when the Issue is resolved, remove this special case match pattern:
809-
StatementKind::FakeRead(box (FakeReadCause::ForGuardBinding, _)) => None,
810-
811-
// Retain spans from all other statements
812-
StatementKind::FakeRead(box (_, _)) // Not including `ForGuardBinding`
813-
| StatementKind::Intrinsic(..)
814-
| StatementKind::Assign(_)
815-
| StatementKind::SetDiscriminant { .. }
816-
| StatementKind::Deinit(..)
817-
| StatementKind::Retag(_, _)
818-
| StatementKind::PlaceMention(..)
819-
| StatementKind::AscribeUserType(_, _) => {
820-
Some(statement.source_info.span)
821-
}
822-
}
823-
}
824-
825-
/// If the MIR `Terminator` has a span contributive to computing coverage spans,
826-
/// return it; otherwise return `None`.
827-
fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Span> {
828-
match terminator.kind {
829-
// These terminators have spans that don't positively contribute to computing a reasonable
830-
// span of actually executed source code. (For example, SwitchInt terminators extracted from
831-
// an `if condition { block }` has a span that includes the executed block, if true,
832-
// but for coverage, the code region executed, up to *and* through the SwitchInt,
833-
// actually stops before the if's block.)
834-
TerminatorKind::Unreachable // Unreachable blocks are not connected to the MIR CFG
835-
| TerminatorKind::Assert { .. }
836-
| TerminatorKind::Drop { .. }
837-
| TerminatorKind::SwitchInt { .. }
838-
// For `FalseEdge`, only the `real` branch is taken, so it is similar to a `Goto`.
839-
| TerminatorKind::FalseEdge { .. }
840-
| TerminatorKind::Goto { .. } => None,
841-
842-
// Call `func` operand can have a more specific span when part of a chain of calls
843-
| TerminatorKind::Call { ref func, .. } => {
844-
let mut span = terminator.source_info.span;
845-
if let mir::Operand::Constant(box constant) = func {
846-
if constant.span.lo() > span.lo() {
847-
span = span.with_lo(constant.span.lo());
848-
}
849-
}
850-
Some(span)
851-
}
852-
853-
// Retain spans from all other terminators
854-
TerminatorKind::UnwindResume
855-
| TerminatorKind::UnwindTerminate(_)
856-
| TerminatorKind::Return
857-
| TerminatorKind::Yield { .. }
858-
| TerminatorKind::GeneratorDrop
859-
| TerminatorKind::FalseUnwind { .. }
860-
| TerminatorKind::InlineAsm { .. } => {
861-
Some(terminator.source_info.span)
862-
}
863-
}
864-
}
865-
866-
/// Returns an extrapolated span (pre-expansion[^1]) corresponding to a range
867-
/// within the function's body source. This span is guaranteed to be contained
868-
/// within, or equal to, the `body_span`. If the extrapolated span is not
869-
/// contained within the `body_span`, the `body_span` is returned.
870-
///
871-
/// [^1]Expansions result from Rust syntax including macros, syntactic sugar,
872-
/// etc.).
873-
#[inline]
874-
fn function_source_span(span: Span, body_span: Span) -> Span {
875-
let original_span = original_sp(span, body_span).with_ctxt(body_span.ctxt());
876-
if body_span.contains(original_span) { original_span } else { body_span }
877-
}

0 commit comments

Comments
 (0)