about summary refs log tree commit diff
path: root/compiler/rustc_mir_transform/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-04-23 00:05:31 +0000
committerbors <bors@rust-lang.org>2024-04-23 00:05:31 +0000
commit9cf10bcf5b368de79abc24fc4d50a9d85b377ffa (patch)
tree975fed41d85532188712e2944555a73106f0f538 /compiler/rustc_mir_transform/src
parent25087e02b34775520856b6cc15e50f5ed0c35f50 (diff)
parent000d0f9116c24c0e24a30e18bfd84f913b099520 (diff)
Auto merge of #124271 - GuillaumeGomez:rollup-7st9wd7, r=GuillaumeGomez
Rollup of 7 pull requests

Successful merges:

 - #115913 (checked_ilog: improve performance)
 - #124178 ([cleanup] [llvm backend] Prevent creating the same `Instance::mono` multiple times)
 - #124183 (Stop taking `ParamTy`/`ParamConst`/`EarlyParamRegion`/`AliasTy` by ref)
 - #124217 (coverage: Prepare for improved branch coverage)
 - #124230 (Stabilize generic `NonZero`.)
 - #124252 (Improve ICE message for forbidden dep-graph reads.)
 - #124268 (Update books)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler/rustc_mir_transform/src')
-rw-r--r--compiler/rustc_mir_transform/src/coverage/mod.rs38
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans.rs47
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs76
3 files changed, 117 insertions, 44 deletions
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index 9e8648b0f93..0b15c52c281 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -9,7 +9,7 @@ mod tests;
 
 use self::counters::{CounterIncrementSite, CoverageCounters};
 use self::graph::{BasicCoverageBlock, CoverageGraph};
-use self::spans::{BcbMapping, BcbMappingKind, CoverageSpans};
+use self::spans::{BcbBranchPair, BcbMapping, BcbMappingKind, CoverageSpans};
 
 use crate::MirPass;
 
@@ -141,21 +141,25 @@ fn create_mappings<'tcx>(
 
     let mut mappings = Vec::new();
 
-    mappings.extend(coverage_spans.all_bcb_mappings().filter_map(
+    mappings.extend(coverage_spans.mappings.iter().filter_map(
         |BcbMapping { kind: bcb_mapping_kind, span }| {
             let kind = match *bcb_mapping_kind {
                 BcbMappingKind::Code(bcb) => MappingKind::Code(term_for_bcb(bcb)),
-                BcbMappingKind::Branch { true_bcb, false_bcb } => MappingKind::Branch {
-                    true_term: term_for_bcb(true_bcb),
-                    false_term: term_for_bcb(false_bcb),
-                },
-                BcbMappingKind::MCDCBranch { true_bcb, false_bcb, condition_info } => {
-                    MappingKind::MCDCBranch {
+                BcbMappingKind::MCDCBranch { true_bcb, false_bcb, condition_info: None } => {
+                    MappingKind::Branch {
                         true_term: term_for_bcb(true_bcb),
                         false_term: term_for_bcb(false_bcb),
-                        mcdc_params: condition_info,
                     }
                 }
+                BcbMappingKind::MCDCBranch {
+                    true_bcb,
+                    false_bcb,
+                    condition_info: Some(mcdc_params),
+                } => MappingKind::MCDCBranch {
+                    true_term: term_for_bcb(true_bcb),
+                    false_term: term_for_bcb(false_bcb),
+                    mcdc_params,
+                },
                 BcbMappingKind::MCDCDecision { bitmap_idx, conditions_num, .. } => {
                     MappingKind::MCDCDecision(DecisionInfo { bitmap_idx, conditions_num })
                 }
@@ -165,6 +169,16 @@ fn create_mappings<'tcx>(
         },
     ));
 
+    mappings.extend(coverage_spans.branch_pairs.iter().filter_map(
+        |&BcbBranchPair { span, true_bcb, false_bcb }| {
+            let true_term = term_for_bcb(true_bcb);
+            let false_term = term_for_bcb(false_bcb);
+            let kind = MappingKind::Branch { true_term, false_term };
+            let code_region = make_code_region(source_map, file_name, span, body_span)?;
+            Some(Mapping { kind, code_region })
+        },
+    ));
+
     mappings
 }
 
@@ -233,7 +247,7 @@ fn inject_mcdc_statements<'tcx>(
 
     // Inject test vector update first because `inject_statement` always insert new statement at head.
     for (end_bcbs, bitmap_idx) in
-        coverage_spans.all_bcb_mappings().filter_map(|mapping| match &mapping.kind {
+        coverage_spans.mappings.iter().filter_map(|mapping| match &mapping.kind {
             BcbMappingKind::MCDCDecision { end_bcbs, bitmap_idx, .. } => {
                 Some((end_bcbs, *bitmap_idx))
             }
@@ -247,9 +261,9 @@ fn inject_mcdc_statements<'tcx>(
     }
 
     for (true_bcb, false_bcb, condition_id) in
-        coverage_spans.all_bcb_mappings().filter_map(|mapping| match mapping.kind {
+        coverage_spans.mappings.iter().filter_map(|mapping| match mapping.kind {
             BcbMappingKind::MCDCBranch { true_bcb, false_bcb, condition_info } => {
-                Some((true_bcb, false_bcb, condition_info.condition_id))
+                Some((true_bcb, false_bcb, condition_info?.condition_id))
             }
             _ => None,
         })
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index a4cd8a38c66..88f18b72085 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -15,13 +15,17 @@ mod from_mir;
 pub(super) enum BcbMappingKind {
     /// Associates an ordinary executable code span with its corresponding BCB.
     Code(BasicCoverageBlock),
-    /// Associates a branch span with BCBs for its true and false arms.
-    Branch { true_bcb: BasicCoverageBlock, false_bcb: 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,
-        condition_info: ConditionInfo,
+        /// If `None`, this actually represents a normal branch mapping inserted
+        /// for code that was too complex for MC/DC.
+        condition_info: Option<ConditionInfo>,
     },
     /// Associates a mcdc decision with its join BCB.
     MCDCDecision { end_bcbs: BTreeSet<BasicCoverageBlock>, bitmap_idx: u32, conditions_num: u16 },
@@ -33,9 +37,20 @@ pub(super) struct BcbMapping {
     pub(super) span: Span,
 }
 
+/// This is separate from [`BcbMappingKind`] 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) span: Span,
+    pub(super) true_bcb: BasicCoverageBlock,
+    pub(super) false_bcb: BasicCoverageBlock,
+}
+
 pub(super) struct CoverageSpans {
     bcb_has_mappings: BitSet<BasicCoverageBlock>,
-    mappings: Vec<BcbMapping>,
+    pub(super) mappings: Vec<BcbMapping>,
+    pub(super) branch_pairs: Vec<BcbBranchPair>,
     test_vector_bitmap_bytes: u32,
 }
 
@@ -44,10 +59,6 @@ impl CoverageSpans {
         self.bcb_has_mappings.contains(bcb)
     }
 
-    pub(super) fn all_bcb_mappings(&self) -> impl Iterator<Item = &BcbMapping> {
-        self.mappings.iter()
-    }
-
     pub(super) fn test_vector_bitmap_bytes(&self) -> u32 {
         self.test_vector_bitmap_bytes
     }
@@ -63,6 +74,7 @@ pub(super) fn generate_coverage_spans(
     basic_coverage_blocks: &CoverageGraph,
 ) -> Option<CoverageSpans> {
     let mut mappings = vec![];
+    let mut branch_pairs = vec![];
 
     if hir_info.is_async_fn {
         // An async function desugars into a function that returns a future,
@@ -84,14 +96,20 @@ pub(super) fn generate_coverage_spans(
             BcbMapping { kind: BcbMappingKind::Code(bcb), span }
         }));
 
-        mappings.extend(from_mir::extract_branch_mappings(
+        branch_pairs.extend(from_mir::extract_branch_pairs(
+            mir_body,
+            hir_info,
+            basic_coverage_blocks,
+        ));
+
+        mappings.extend(from_mir::extract_mcdc_mappings(
             mir_body,
             hir_info.body_span,
             basic_coverage_blocks,
         ));
     }
 
-    if mappings.is_empty() {
+    if mappings.is_empty() && branch_pairs.is_empty() {
         return None;
     }
 
@@ -104,8 +122,7 @@ pub(super) fn generate_coverage_spans(
     for BcbMapping { kind, span: _ } in &mappings {
         match *kind {
             BcbMappingKind::Code(bcb) => insert(bcb),
-            BcbMappingKind::Branch { true_bcb, false_bcb }
-            | BcbMappingKind::MCDCBranch { true_bcb, false_bcb, .. } => {
+            BcbMappingKind::MCDCBranch { true_bcb, false_bcb, .. } => {
                 insert(true_bcb);
                 insert(false_bcb);
             }
@@ -118,8 +135,12 @@ pub(super) fn generate_coverage_spans(
             }
         }
     }
+    for &BcbBranchPair { true_bcb, false_bcb, .. } in &branch_pairs {
+        insert(true_bcb);
+        insert(false_bcb);
+    }
 
-    Some(CoverageSpans { bcb_has_mappings, mappings, test_vector_bitmap_bytes })
+    Some(CoverageSpans { bcb_has_mappings, mappings, branch_pairs, test_vector_bitmap_bytes })
 }
 
 #[derive(Debug)]
diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
index b9919a2ae88..64f21d74b1c 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
@@ -13,7 +13,7 @@ use rustc_span::{ExpnKind, MacroKind, Span, Symbol};
 use crate::coverage::graph::{
     BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB,
 };
-use crate::coverage::spans::{BcbMapping, BcbMappingKind};
+use crate::coverage::spans::{BcbBranchPair, BcbMapping, BcbMappingKind};
 use crate::coverage::ExtractedHirInfo;
 
 /// Traverses the MIR body to produce an initial collection of coverage-relevant
@@ -366,15 +366,10 @@ impl SpanFromMir {
     }
 }
 
-pub(super) fn extract_branch_mappings(
+fn resolve_block_markers(
+    branch_info: &mir::coverage::BranchInfo,
     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![];
-    };
-
+) -> IndexVec<BlockMarkerId, Option<BasicBlock>> {
     let mut block_markers = IndexVec::<BlockMarkerId, Option<BasicBlock>>::from_elem_n(
         None,
         branch_info.num_block_markers,
@@ -389,6 +384,58 @@ pub(super) fn extract_branch_mappings(
         }
     }
 
+    block_markers
+}
+
+// FIXME: There is currently a lot of redundancy between
+// `extract_branch_pairs` and `extract_mcdc_mappings`. This is needed so
+// that they can each be modified without interfering with the other, but in
+// the long term we should try to bring them together again when branch coverage
+// and MC/DC coverage support are more mature.
+
+pub(super) fn extract_branch_pairs(
+    mir_body: &mir::Body<'_>,
+    hir_info: &ExtractedHirInfo,
+    basic_coverage_blocks: &CoverageGraph,
+) -> Vec<BcbBranchPair> {
+    let Some(branch_info) = mir_body.coverage_branch_info.as_deref() else { return vec![] };
+
+    let block_markers = resolve_block_markers(branch_info, mir_body);
+
+    branch_info
+        .branch_spans
+        .iter()
+        .filter_map(|&BranchSpan { span: raw_span, true_marker, false_marker }| {
+            // For now, ignore any branch span that was introduced by
+            // expansion. This makes things like assert macros less noisy.
+            if !raw_span.ctxt().outer_expn_data().is_root() {
+                return None;
+            }
+            let (span, _) =
+                unexpand_into_body_span_with_visible_macro(raw_span, hir_info.body_span)?;
+
+            let bcb_from_marker =
+                |marker: BlockMarkerId| basic_coverage_blocks.bcb_from_bb(block_markers[marker]?);
+
+            let true_bcb = bcb_from_marker(true_marker)?;
+            let false_bcb = bcb_from_marker(false_marker)?;
+
+            Some(BcbBranchPair { span, true_bcb, false_bcb })
+        })
+        .collect::<Vec<_>>()
+}
+
+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![];
+    };
+
+    let block_markers = resolve_block_markers(branch_info, mir_body);
+
     let bcb_from_marker =
         |marker: BlockMarkerId| basic_coverage_blocks.bcb_from_bb(block_markers[marker]?);
 
@@ -406,12 +453,6 @@ pub(super) fn extract_branch_mappings(
             Some((span, true_bcb, false_bcb))
         };
 
-    let branch_filter_map = |&BranchSpan { span: raw_span, true_marker, false_marker }| {
-        check_branch_bcb(raw_span, true_marker, false_marker).map(|(span, true_bcb, false_bcb)| {
-            BcbMapping { kind: BcbMappingKind::Branch { true_bcb, false_bcb }, span }
-        })
-    };
-
     let mcdc_branch_filter_map =
         |&MCDCBranchSpan { span: raw_span, true_marker, false_marker, condition_info }| {
             check_branch_bcb(raw_span, true_marker, false_marker).map(
@@ -446,10 +487,7 @@ pub(super) fn extract_branch_mappings(
         })
     };
 
-    branch_info
-        .branch_spans
-        .iter()
-        .filter_map(branch_filter_map)
+    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<_>>()