|
1 | 1 | use rustc_data_structures::captures::Captures;
|
2 | 2 | use rustc_data_structures::fx::FxHashSet;
|
| 3 | +use rustc_index::IndexVec; |
| 4 | +use rustc_middle::mir::coverage::{BlockMarkerId, BranchSpan, CoverageKind}; |
3 | 5 | use rustc_middle::mir::{
|
4 |
| - self, AggregateKind, FakeReadCause, Rvalue, Statement, StatementKind, Terminator, |
| 6 | + self, AggregateKind, BasicBlock, FakeReadCause, Rvalue, Statement, StatementKind, Terminator, |
5 | 7 | TerminatorKind,
|
6 | 8 | };
|
7 | 9 | use rustc_span::{ExpnKind, MacroKind, Span, Symbol};
|
8 | 10 |
|
9 | 11 | use crate::coverage::graph::{
|
10 | 12 | BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB,
|
11 | 13 | };
|
| 14 | +use crate::coverage::spans::{BcbMapping, BcbMappingKind}; |
12 | 15 | use crate::coverage::ExtractedHirInfo;
|
13 | 16 |
|
14 | 17 | /// Traverses the MIR body to produce an initial collection of coverage-relevant
|
@@ -179,8 +182,6 @@ fn is_closure_like(statement: &Statement<'_>) -> bool {
|
179 | 182 | /// If the MIR `Statement` has a span contributive to computing coverage spans,
|
180 | 183 | /// return it; otherwise return `None`.
|
181 | 184 | fn filtered_statement_span(statement: &Statement<'_>) -> Option<Span> {
|
182 |
| - use mir::coverage::CoverageKind; |
183 |
| - |
184 | 185 | match statement.kind {
|
185 | 186 | // These statements have spans that are often outside the scope of the executed source code
|
186 | 187 | // for their parent `BasicBlock`.
|
@@ -363,3 +364,50 @@ impl SpanFromMir {
|
363 | 364 | Self { span, visible_macro, bcb, is_hole }
|
364 | 365 | }
|
365 | 366 | }
|
| 367 | + |
| 368 | +pub(super) fn extract_branch_mappings( |
| 369 | + mir_body: &mir::Body<'_>, |
| 370 | + body_span: Span, |
| 371 | + basic_coverage_blocks: &CoverageGraph, |
| 372 | +) -> Vec<BcbMapping> { |
| 373 | + let Some(hir_branch_info) = mir_body.coverage_hir_branch_info.as_deref() else { |
| 374 | + return vec![]; |
| 375 | + }; |
| 376 | + |
| 377 | + let mut block_markers = IndexVec::<BlockMarkerId, Option<BasicBlock>>::from_elem_n( |
| 378 | + None, |
| 379 | + hir_branch_info.num_block_markers, |
| 380 | + ); |
| 381 | + |
| 382 | + for (bb, data) in mir_body.basic_blocks.iter_enumerated() { |
| 383 | + for statement in &data.statements { |
| 384 | + if let StatementKind::Coverage(coverage) = &statement.kind { |
| 385 | + if let CoverageKind::BlockMarker { id } = coverage.kind { |
| 386 | + block_markers[id] = Some(bb); |
| 387 | + } |
| 388 | + } |
| 389 | + } |
| 390 | + } |
| 391 | + |
| 392 | + hir_branch_info |
| 393 | + .branch_spans |
| 394 | + .iter() |
| 395 | + .filter_map(|&BranchSpan { span: raw_span, true_marker, false_marker }| { |
| 396 | + // For now, ignore any branch span that was introduced by |
| 397 | + // expansion. This makes things like assert macros less noisy. |
| 398 | + if !raw_span.ctxt().outer_expn_data().is_root() { |
| 399 | + return None; |
| 400 | + } |
| 401 | + let (span, _) = unexpand_into_body_span_with_visible_macro(raw_span, body_span)?; |
| 402 | + |
| 403 | + let bcb_from_marker = |marker: BlockMarkerId| { |
| 404 | + Some(basic_coverage_blocks.bcb_from_bb(block_markers[marker]?)?) |
| 405 | + }; |
| 406 | + |
| 407 | + let true_bcb = bcb_from_marker(true_marker)?; |
| 408 | + let false_bcb = bcb_from_marker(false_marker)?; |
| 409 | + |
| 410 | + Some(BcbMapping { kind: BcbMappingKind::Branch { true_bcb, false_bcb }, span }) |
| 411 | + }) |
| 412 | + .collect::<Vec<_>>() |
| 413 | +} |
0 commit comments