|  | 
| 1 | 1 | use rustc_data_structures::captures::Captures; | 
|  | 2 | +use rustc_data_structures::graph::WithNumNodes; | 
|  | 3 | +use rustc_index::bit_set::BitSet; | 
|  | 4 | +use rustc_index::IndexVec; | 
|  | 5 | +use rustc_middle::mir::coverage::{BlockMarkerId, BranchSpan, CoverageKind}; | 
| 2 | 6 | use rustc_middle::mir::{ | 
| 3 |  | -    self, AggregateKind, FakeReadCause, Rvalue, Statement, StatementKind, Terminator, | 
|  | 7 | +    self, AggregateKind, BasicBlock, FakeReadCause, Rvalue, Statement, StatementKind, Terminator, | 
| 4 | 8 |     TerminatorKind, | 
| 5 | 9 | }; | 
| 6 | 10 | use rustc_span::Span; | 
| 7 | 11 | 
 | 
| 8 | 12 | use crate::coverage::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph}; | 
| 9 |  | -use crate::coverage::spans::CoverageSpan; | 
|  | 13 | +use crate::coverage::spans::{BcbBranchSpan, CoverageSpan}; | 
| 10 | 14 | 
 | 
| 11 | 15 | pub(super) fn mir_to_initial_sorted_coverage_spans( | 
| 12 | 16 |     mir_body: &mir::Body<'_>, | 
| @@ -191,3 +195,50 @@ fn function_source_span(span: Span, body_span: Span) -> Option<Span> { | 
| 191 | 195 |     let original_span = original_sp(span, body_span).with_ctxt(body_span.ctxt()); | 
| 192 | 196 |     body_span.contains(original_span).then_some(original_span) | 
| 193 | 197 | } | 
|  | 198 | + | 
|  | 199 | +pub(super) fn extract_branch_spans( | 
|  | 200 | +    mir_body: &mir::Body<'_>, | 
|  | 201 | +    body_span: Span, | 
|  | 202 | +    basic_coverage_blocks: &CoverageGraph, | 
|  | 203 | +) -> (BitSet<BasicCoverageBlock>, Vec<BcbBranchSpan>) { | 
|  | 204 | +    let mut bcbs_with_branch_spans = BitSet::new_empty(basic_coverage_blocks.num_nodes()); | 
|  | 205 | +    let mut branch_spans = Vec::new(); | 
|  | 206 | + | 
|  | 207 | +    if let Some(coverage_hir_info) = mir_body.coverage_hir_info.as_deref() { | 
|  | 208 | +        let mut block_markers = IndexVec::<BlockMarkerId, Option<BasicBlock>>::from_elem_n( | 
|  | 209 | +            None, | 
|  | 210 | +            coverage_hir_info.num_block_markers, | 
|  | 211 | +        ); | 
|  | 212 | + | 
|  | 213 | +        for (bb, data) in mir_body.basic_blocks.iter_enumerated() { | 
|  | 214 | +            for statement in &data.statements { | 
|  | 215 | +                if let StatementKind::Coverage(coverage) = &statement.kind { | 
|  | 216 | +                    if let CoverageKind::BlockMarker { id } = coverage.kind { | 
|  | 217 | +                        block_markers[id] = Some(bb); | 
|  | 218 | +                    } | 
|  | 219 | +                } | 
|  | 220 | +            } | 
|  | 221 | +        } | 
|  | 222 | + | 
|  | 223 | +        // Assume that most branch spans will resolve successfully. | 
|  | 224 | +        branch_spans.reserve(coverage_hir_info.branch_spans.len()); | 
|  | 225 | +        branch_spans.extend(coverage_hir_info.branch_spans.iter().filter_map( | 
|  | 226 | +            |&BranchSpan { span: raw_span, true_marker, false_marker }| { | 
|  | 227 | +                let span = function_source_span(raw_span, body_span)?; | 
|  | 228 | + | 
|  | 229 | +                let bcb_from_marker = |marker: BlockMarkerId| { | 
|  | 230 | +                    Some(basic_coverage_blocks.bcb_from_bb(block_markers[marker]?)?) | 
|  | 231 | +                }; | 
|  | 232 | + | 
|  | 233 | +                let true_bcb = bcb_from_marker(true_marker)?; | 
|  | 234 | +                let false_bcb = bcb_from_marker(false_marker)?; | 
|  | 235 | + | 
|  | 236 | +                bcbs_with_branch_spans.insert(true_bcb); | 
|  | 237 | +                bcbs_with_branch_spans.insert(false_bcb); | 
|  | 238 | +                Some(BcbBranchSpan { span, true_bcb, false_bcb }) | 
|  | 239 | +            }, | 
|  | 240 | +        )); | 
|  | 241 | +    } | 
|  | 242 | + | 
|  | 243 | +    (bcbs_with_branch_spans, branch_spans) | 
|  | 244 | +} | 
0 commit comments