about summary refs log tree commit diff
path: root/compiler/rustc_mir_transform/src/coverage/mappings.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_transform/src/coverage/mappings.rs')
-rw-r--r--compiler/rustc_mir_transform/src/coverage/mappings.rs213
1 files changed, 109 insertions, 104 deletions
diff --git a/compiler/rustc_mir_transform/src/coverage/mappings.rs b/compiler/rustc_mir_transform/src/coverage/mappings.rs
index d364658efb6..ddbe1333c4b 100644
--- a/compiler/rustc_mir_transform/src/coverage/mappings.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mappings.rs
@@ -2,9 +2,8 @@ use std::collections::BTreeSet;
 
 use rustc_data_structures::graph::DirectedGraph;
 use rustc_index::bit_set::BitSet;
-use rustc_middle::mir::coverage::{
-    BlockMarkerId, BranchSpan, ConditionInfo, CoverageKind, MCDCBranchSpan, MCDCDecisionSpan,
-};
+use rustc_index::IndexVec;
+use rustc_middle::mir::coverage::{BlockMarkerId, BranchSpan, ConditionInfo, CoverageKind};
 use rustc_middle::mir::{self, BasicBlock, StatementKind};
 use rustc_span::Span;
 
@@ -13,55 +12,53 @@ use crate::coverage::spans::{
     extract_refined_covspans, unexpand_into_body_span_with_visible_macro,
 };
 use crate::coverage::ExtractedHirInfo;
-use rustc_index::IndexVec;
-
-#[derive(Clone, Debug)]
-pub(super) enum BcbMappingKind {
-    /// Associates an ordinary executable code span with its corresponding BCB.
-    Code(BasicCoverageBlock),
-
-    // Ordinary branch mappings are stored separately, so they don't have a
-    // variant in this enum.
-    //
-    /// Associates a mcdc branch span with condition info besides fields for normal branch.
-    MCDCBranch {
-        true_bcb: BasicCoverageBlock,
-        false_bcb: BasicCoverageBlock,
-        /// If `None`, this actually represents a normal branch mapping inserted
-        /// for code that was too complex for MC/DC.
-        condition_info: Option<ConditionInfo>,
-        decision_depth: u16,
-    },
-    /// Associates a mcdc decision with its join BCB.
-    MCDCDecision {
-        end_bcbs: BTreeSet<BasicCoverageBlock>,
-        bitmap_idx: u32,
-        conditions_num: u16,
-        decision_depth: u16,
-    },
-}
 
+/// Associates an ordinary executable code span with its corresponding BCB.
 #[derive(Debug)]
-pub(super) struct BcbMapping {
-    pub(super) kind: BcbMappingKind,
+pub(super) struct CodeMapping {
     pub(super) span: Span,
+    pub(super) bcb: BasicCoverageBlock,
 }
 
-/// This is separate from [`BcbMappingKind`] to help prepare for larger changes
+/// This is separate from [`MCDCBranch`] to help prepare for larger changes
 /// that will be needed for improved branch coverage in the future.
 /// (See <https://github.com/rust-lang/rust/pull/124217>.)
 #[derive(Debug)]
-pub(super) struct BcbBranchPair {
+pub(super) struct BranchPair {
     pub(super) span: Span,
     pub(super) true_bcb: BasicCoverageBlock,
     pub(super) false_bcb: BasicCoverageBlock,
 }
 
+/// Associates an MC/DC branch span with condition info besides fields for normal branch.
+#[derive(Debug)]
+pub(super) struct MCDCBranch {
+    pub(super) span: Span,
+    pub(super) true_bcb: BasicCoverageBlock,
+    pub(super) false_bcb: BasicCoverageBlock,
+    /// If `None`, this actually represents a normal branch mapping inserted
+    /// for code that was too complex for MC/DC.
+    pub(super) condition_info: Option<ConditionInfo>,
+    pub(super) decision_depth: u16,
+}
+
+/// Associates an MC/DC decision with its join BCBs.
+#[derive(Debug)]
+pub(super) struct MCDCDecision {
+    pub(super) span: Span,
+    pub(super) end_bcbs: BTreeSet<BasicCoverageBlock>,
+    pub(super) bitmap_idx: u32,
+    pub(super) conditions_num: u16,
+    pub(super) decision_depth: u16,
+}
+
 pub(super) struct CoverageSpans {
     bcb_has_mappings: BitSet<BasicCoverageBlock>,
-    pub(super) mappings: Vec<BcbMapping>,
-    pub(super) branch_pairs: Vec<BcbBranchPair>,
+    pub(super) code_mappings: Vec<CodeMapping>,
+    pub(super) branch_pairs: Vec<BranchPair>,
     test_vector_bitmap_bytes: u32,
+    pub(super) mcdc_branches: Vec<MCDCBranch>,
+    pub(super) mcdc_decisions: Vec<MCDCDecision>,
 }
 
 impl CoverageSpans {
@@ -83,8 +80,10 @@ pub(super) fn generate_coverage_spans(
     hir_info: &ExtractedHirInfo,
     basic_coverage_blocks: &CoverageGraph,
 ) -> Option<CoverageSpans> {
-    let mut mappings = vec![];
+    let mut code_mappings = vec![];
     let mut branch_pairs = vec![];
+    let mut mcdc_branches = vec![];
+    let mut mcdc_decisions = vec![];
 
     if hir_info.is_async_fn {
         // An async function desugars into a function that returns a future,
@@ -92,17 +91,27 @@ pub(super) fn generate_coverage_spans(
         // outer function will be unhelpful, so just keep the signature span
         // and ignore all of the spans in the MIR body.
         if let Some(span) = hir_info.fn_sig_span_extended {
-            mappings.push(BcbMapping { kind: BcbMappingKind::Code(START_BCB), span });
+            code_mappings.push(CodeMapping { span, bcb: START_BCB });
         }
     } else {
-        extract_refined_covspans(mir_body, hir_info, basic_coverage_blocks, &mut mappings);
+        extract_refined_covspans(mir_body, hir_info, basic_coverage_blocks, &mut code_mappings);
 
         branch_pairs.extend(extract_branch_pairs(mir_body, hir_info, basic_coverage_blocks));
 
-        mappings.extend(extract_mcdc_mappings(mir_body, hir_info.body_span, basic_coverage_blocks));
+        extract_mcdc_mappings(
+            mir_body,
+            hir_info.body_span,
+            basic_coverage_blocks,
+            &mut mcdc_branches,
+            &mut mcdc_decisions,
+        );
     }
 
-    if mappings.is_empty() && branch_pairs.is_empty() {
+    if code_mappings.is_empty()
+        && branch_pairs.is_empty()
+        && mcdc_branches.is_empty()
+        && mcdc_decisions.is_empty()
+    {
         return None;
     }
 
@@ -111,29 +120,36 @@ pub(super) fn generate_coverage_spans(
     let mut insert = |bcb| {
         bcb_has_mappings.insert(bcb);
     };
-    let mut test_vector_bitmap_bytes = 0;
-    for BcbMapping { kind, span: _ } in &mappings {
-        match *kind {
-            BcbMappingKind::Code(bcb) => insert(bcb),
-            BcbMappingKind::MCDCBranch { true_bcb, false_bcb, .. } => {
-                insert(true_bcb);
-                insert(false_bcb);
-            }
-            BcbMappingKind::MCDCDecision { bitmap_idx, conditions_num, .. } => {
-                // `bcb_has_mappings` is used for inject coverage counters
-                // but they are not needed for decision BCBs.
-                // While the length of test vector bitmap should be calculated here.
-                test_vector_bitmap_bytes = test_vector_bitmap_bytes
-                    .max(bitmap_idx + (1_u32 << conditions_num as u32).div_ceil(8));
-            }
-        }
+
+    for &CodeMapping { span: _, bcb } in &code_mappings {
+        insert(bcb);
+    }
+    for &BranchPair { true_bcb, false_bcb, .. } in &branch_pairs {
+        insert(true_bcb);
+        insert(false_bcb);
     }
-    for &BcbBranchPair { true_bcb, false_bcb, .. } in &branch_pairs {
+    for &MCDCBranch { true_bcb, false_bcb, .. } in &mcdc_branches {
         insert(true_bcb);
         insert(false_bcb);
     }
 
-    Some(CoverageSpans { bcb_has_mappings, mappings, branch_pairs, test_vector_bitmap_bytes })
+    // Determine the length of the test vector bitmap.
+    let test_vector_bitmap_bytes = mcdc_decisions
+        .iter()
+        .map(|&MCDCDecision { bitmap_idx, conditions_num, .. }| {
+            bitmap_idx + (1_u32 << u32::from(conditions_num)).div_ceil(8)
+        })
+        .max()
+        .unwrap_or(0);
+
+    Some(CoverageSpans {
+        bcb_has_mappings,
+        code_mappings,
+        branch_pairs,
+        test_vector_bitmap_bytes,
+        mcdc_branches,
+        mcdc_decisions,
+    })
 }
 
 fn resolve_block_markers(
@@ -167,7 +183,7 @@ pub(super) fn extract_branch_pairs(
     mir_body: &mir::Body<'_>,
     hir_info: &ExtractedHirInfo,
     basic_coverage_blocks: &CoverageGraph,
-) -> Vec<BcbBranchPair> {
+) -> Vec<BranchPair> {
     let Some(branch_info) = mir_body.coverage_branch_info.as_deref() else { return vec![] };
 
     let block_markers = resolve_block_markers(branch_info, mir_body);
@@ -190,7 +206,7 @@ pub(super) fn extract_branch_pairs(
             let true_bcb = bcb_from_marker(true_marker)?;
             let false_bcb = bcb_from_marker(false_marker)?;
 
-            Some(BcbBranchPair { span, true_bcb, false_bcb })
+            Some(BranchPair { span, true_bcb, false_bcb })
         })
         .collect::<Vec<_>>()
 }
@@ -199,10 +215,10 @@ pub(super) fn extract_mcdc_mappings(
     mir_body: &mir::Body<'_>,
     body_span: Span,
     basic_coverage_blocks: &CoverageGraph,
-) -> Vec<BcbMapping> {
-    let Some(branch_info) = mir_body.coverage_branch_info.as_deref() else {
-        return vec![];
-    };
+    mcdc_branches: &mut impl Extend<MCDCBranch>,
+    mcdc_decisions: &mut impl Extend<MCDCDecision>,
+) {
+    let Some(branch_info) = mir_body.coverage_branch_info.as_deref() else { return };
 
     let block_markers = resolve_block_markers(branch_info, mir_body);
 
@@ -223,53 +239,42 @@ pub(super) fn extract_mcdc_mappings(
             Some((span, true_bcb, false_bcb))
         };
 
-    let mcdc_branch_filter_map = |&MCDCBranchSpan {
-                                      span: raw_span,
-                                      true_marker,
-                                      false_marker,
-                                      condition_info,
-                                      decision_depth,
-                                  }| {
-        check_branch_bcb(raw_span, true_marker, false_marker).map(|(span, true_bcb, false_bcb)| {
-            BcbMapping {
-                kind: BcbMappingKind::MCDCBranch {
-                    true_bcb,
-                    false_bcb,
-                    condition_info,
-                    decision_depth,
-                },
-                span,
-            }
-        })
-    };
+    mcdc_branches.extend(branch_info.mcdc_branch_spans.iter().filter_map(
+        |&mir::coverage::MCDCBranchSpan {
+             span: raw_span,
+             condition_info,
+             true_marker,
+             false_marker,
+             decision_depth,
+         }| {
+            let (span, true_bcb, false_bcb) =
+                check_branch_bcb(raw_span, true_marker, false_marker)?;
+            Some(MCDCBranch { span, true_bcb, false_bcb, condition_info, decision_depth })
+        },
+    ));
 
     let mut next_bitmap_idx = 0;
 
-    let decision_filter_map = |decision: &MCDCDecisionSpan| {
-        let (span, _) = unexpand_into_body_span_with_visible_macro(decision.span, body_span)?;
+    mcdc_decisions.extend(branch_info.mcdc_decision_spans.iter().filter_map(
+        |decision: &mir::coverage::MCDCDecisionSpan| {
+            let (span, _) = unexpand_into_body_span_with_visible_macro(decision.span, body_span)?;
 
-        let end_bcbs = decision
-            .end_markers
-            .iter()
-            .map(|&marker| bcb_from_marker(marker))
-            .collect::<Option<_>>()?;
+            let end_bcbs = decision
+                .end_markers
+                .iter()
+                .map(|&marker| bcb_from_marker(marker))
+                .collect::<Option<_>>()?;
 
-        let bitmap_idx = next_bitmap_idx;
-        next_bitmap_idx += (1_u32 << decision.conditions_num).div_ceil(8);
+            let bitmap_idx = next_bitmap_idx;
+            next_bitmap_idx += (1_u32 << decision.conditions_num).div_ceil(8);
 
-        Some(BcbMapping {
-            kind: BcbMappingKind::MCDCDecision {
+            Some(MCDCDecision {
+                span,
                 end_bcbs,
                 bitmap_idx,
                 conditions_num: decision.conditions_num as u16,
                 decision_depth: decision.decision_depth,
-            },
-            span,
-        })
-    };
-
-    std::iter::empty()
-        .chain(branch_info.mcdc_branch_spans.iter().filter_map(mcdc_branch_filter_map))
-        .chain(branch_info.mcdc_decision_spans.iter().filter_map(decision_filter_map))
-        .collect::<Vec<_>>()
+            })
+        },
+    ));
 }