|
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