|
1 | | -use super::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB}; |
| 1 | +use std::cell::OnceCell; |
2 | 2 |
|
3 | 3 | use rustc_data_structures::graph::WithNumNodes; |
4 | 4 | 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}; |
10 | 6 | use rustc_span::{BytePos, ExpnKind, MacroKind, Span, Symbol}; |
11 | 7 |
|
12 | | -use std::cell::OnceCell; |
| 8 | +use super::graph::{BasicCoverageBlock, CoverageGraph, START_BCB}; |
| 9 | + |
| 10 | +mod from_mir; |
13 | 11 |
|
14 | 12 | pub(super) struct CoverageSpans { |
15 | 13 | /// Map from BCBs to their list of coverage spans. |
@@ -311,41 +309,6 @@ impl<'a, 'tcx> CoverageSpansGenerator<'a, 'tcx> { |
311 | 309 | coverage_spans.to_refined_spans() |
312 | 310 | } |
313 | 311 |
|
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 | | - |
349 | 312 | /// Iterate through the sorted `CoverageSpan`s, and return the refined list of merged and |
350 | 313 | /// de-duplicated `CoverageSpan`s. |
351 | 314 | fn to_refined_spans(mut self) -> Vec<CoverageSpan> { |
@@ -485,48 +448,6 @@ impl<'a, 'tcx> CoverageSpansGenerator<'a, 'tcx> { |
485 | 448 | } |
486 | 449 | } |
487 | 450 |
|
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 | | - |
530 | 451 | fn curr(&self) -> &CoverageSpan { |
531 | 452 | self.some_curr |
532 | 453 | .as_ref() |
@@ -774,104 +695,3 @@ impl<'a, 'tcx> CoverageSpansGenerator<'a, 'tcx> { |
774 | 695 | self.basic_coverage_blocks.dominates(dom_covspan.bcb, covspan.bcb) |
775 | 696 | } |
776 | 697 | } |
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