|
| 1 | +use std::iter; |
| 2 | + |
1 | 3 | use rustc_middle::bug;
|
2 | 4 | use rustc_middle::mir::coverage::CoverageKind;
|
3 | 5 | use rustc_middle::mir::{
|
4 | 6 | self, FakeReadCause, Statement, StatementKind, Terminator, TerminatorKind,
|
5 | 7 | };
|
6 | 8 | use rustc_span::{ExpnKind, Span};
|
7 | 9 |
|
8 |
| -use crate::coverage::ExtractedHirInfo; |
9 |
| -use crate::coverage::graph::{ |
10 |
| - BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB, |
11 |
| -}; |
| 10 | +use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph, START_BCB}; |
12 | 11 | use crate::coverage::spans::Covspan;
|
13 |
| -use crate::coverage::unexpand::unexpand_into_body_span_with_expn_kind; |
14 | 12 |
|
15 |
| -pub(crate) struct ExtractedCovspans { |
16 |
| - pub(crate) covspans: Vec<SpanFromMir>, |
| 13 | +#[derive(Debug)] |
| 14 | +pub(crate) struct RawSpanFromMir { |
| 15 | + /// A span that has been extracted from a MIR statement/terminator, but |
| 16 | + /// hasn't been "unexpanded", so it might not lie within the function body |
| 17 | + /// span and might be part of an expansion with a different context. |
| 18 | + pub(crate) raw_span: Span, |
| 19 | + pub(crate) bcb: BasicCoverageBlock, |
17 | 20 | }
|
18 | 21 |
|
19 |
| -/// Traverses the MIR body to produce an initial collection of coverage-relevant |
20 |
| -/// spans, each associated with a node in the coverage graph (BCB) and possibly |
21 |
| -/// other metadata. |
22 |
| -pub(crate) fn extract_covspans_from_mir( |
23 |
| - mir_body: &mir::Body<'_>, |
24 |
| - hir_info: &ExtractedHirInfo, |
| 22 | +/// Generates an initial set of coverage spans from the statements and |
| 23 | +/// terminators in the function's MIR body, each associated with its |
| 24 | +/// corresponding node in the coverage graph. |
| 25 | +/// |
| 26 | +/// This is necessarily an inexact process, because MIR isn't designed to |
| 27 | +/// capture source spans at the level of detail we would want for coverage, |
| 28 | +/// but it's good enough to be better than nothing. |
| 29 | +pub(crate) fn extract_raw_spans_from_mir<'tcx>( |
| 30 | + mir_body: &mir::Body<'tcx>, |
25 | 31 | graph: &CoverageGraph,
|
26 |
| -) -> ExtractedCovspans { |
27 |
| - let &ExtractedHirInfo { body_span, .. } = hir_info; |
28 |
| - |
29 |
| - let mut covspans = vec![]; |
| 32 | +) -> Vec<RawSpanFromMir> { |
| 33 | + let mut raw_spans = vec![]; |
30 | 34 |
|
| 35 | + // We only care about blocks that are part of the coverage graph. |
31 | 36 | for (bcb, bcb_data) in graph.iter_enumerated() {
|
32 |
| - bcb_to_initial_coverage_spans(mir_body, body_span, bcb, bcb_data, &mut covspans); |
33 |
| - } |
| 37 | + let make_raw_span = |raw_span: Span| RawSpanFromMir { raw_span, bcb }; |
34 | 38 |
|
35 |
| - // Only add the signature span if we found at least one span in the body. |
36 |
| - if !covspans.is_empty() { |
37 |
| - // If there is no usable signature span, add a fake one (before refinement) |
38 |
| - // to avoid an ugly gap between the body start and the first real span. |
39 |
| - // FIXME: Find a more principled way to solve this problem. |
40 |
| - let fn_sig_span = hir_info.fn_sig_span_extended.unwrap_or_else(|| body_span.shrink_to_lo()); |
41 |
| - covspans.push(SpanFromMir::for_fn_sig(fn_sig_span)); |
42 |
| - } |
| 39 | + // A coverage graph node can consist of multiple basic blocks. |
| 40 | + for &bb in &bcb_data.basic_blocks { |
| 41 | + let bb_data = &mir_body[bb]; |
43 | 42 |
|
44 |
| - ExtractedCovspans { covspans } |
45 |
| -} |
| 43 | + let statements = bb_data.statements.iter(); |
| 44 | + raw_spans.extend(statements.filter_map(filtered_statement_span).map(make_raw_span)); |
46 | 45 |
|
47 |
| -// Generate a set of coverage spans from the filtered set of `Statement`s and `Terminator`s of |
48 |
| -// the `BasicBlock`(s) in the given `BasicCoverageBlockData`. One coverage span is generated |
49 |
| -// for each `Statement` and `Terminator`. (Note that subsequent stages of coverage analysis will |
50 |
| -// merge some coverage spans, at which point a coverage span may represent multiple |
51 |
| -// `Statement`s and/or `Terminator`s.) |
52 |
| -fn bcb_to_initial_coverage_spans<'a, 'tcx>( |
53 |
| - mir_body: &'a mir::Body<'tcx>, |
54 |
| - body_span: Span, |
55 |
| - bcb: BasicCoverageBlock, |
56 |
| - bcb_data: &'a BasicCoverageBlockData, |
57 |
| - initial_covspans: &mut Vec<SpanFromMir>, |
58 |
| -) { |
59 |
| - for &bb in &bcb_data.basic_blocks { |
60 |
| - let data = &mir_body[bb]; |
61 |
| - |
62 |
| - let unexpand = move |expn_span| { |
63 |
| - unexpand_into_body_span_with_expn_kind(expn_span, body_span) |
64 |
| - // Discard any spans that fill the entire body, because they tend |
65 |
| - // to represent compiler-inserted code, e.g. implicitly returning `()`. |
66 |
| - .filter(|(span, _)| !span.source_equal(body_span)) |
67 |
| - }; |
68 |
| - |
69 |
| - let mut extract_statement_span = |statement| { |
70 |
| - let expn_span = filtered_statement_span(statement)?; |
71 |
| - let (span, expn_kind) = unexpand(expn_span)?; |
72 |
| - |
73 |
| - initial_covspans.push(SpanFromMir::new(span, expn_kind, bcb)); |
74 |
| - Some(()) |
75 |
| - }; |
76 |
| - for statement in data.statements.iter() { |
77 |
| - extract_statement_span(statement); |
| 46 | + // There's only one terminator, but wrap it in an iterator to |
| 47 | + // mirror the handling of statements. |
| 48 | + let terminator = iter::once(bb_data.terminator()); |
| 49 | + raw_spans.extend(terminator.filter_map(filtered_terminator_span).map(make_raw_span)); |
78 | 50 | }
|
79 |
| - |
80 |
| - let mut extract_terminator_span = |terminator| { |
81 |
| - let expn_span = filtered_terminator_span(terminator)?; |
82 |
| - let (span, expn_kind) = unexpand(expn_span)?; |
83 |
| - |
84 |
| - initial_covspans.push(SpanFromMir::new(span, expn_kind, bcb)); |
85 |
| - Some(()) |
86 |
| - }; |
87 |
| - extract_terminator_span(data.terminator()); |
88 | 51 | }
|
| 52 | + |
| 53 | + raw_spans |
89 | 54 | }
|
90 | 55 |
|
91 | 56 | /// If the MIR `Statement` has a span contributive to computing coverage spans,
|
@@ -219,7 +184,7 @@ pub(crate) struct SpanFromMir {
|
219 | 184 | }
|
220 | 185 |
|
221 | 186 | impl SpanFromMir {
|
222 |
| - fn for_fn_sig(fn_sig_span: Span) -> Self { |
| 187 | + pub(crate) fn for_fn_sig(fn_sig_span: Span) -> Self { |
223 | 188 | Self::new(fn_sig_span, None, START_BCB)
|
224 | 189 | }
|
225 | 190 |
|
|
0 commit comments