about summary refs log tree commit diff
path: root/compiler/rustc_mir_build/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_build/src')
-rw-r--r--compiler/rustc_mir_build/src/builder/coverageinfo.rs59
-rw-r--r--compiler/rustc_mir_build/src/builder/coverageinfo/mcdc.rs295
-rw-r--r--compiler/rustc_mir_build/src/builder/expr/into.rs2
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/mod.rs10
-rw-r--r--compiler/rustc_mir_build/src/errors.rs9
5 files changed, 7 insertions, 368 deletions
diff --git a/compiler/rustc_mir_build/src/builder/coverageinfo.rs b/compiler/rustc_mir_build/src/builder/coverageinfo.rs
index aa43b273cff..14199c20921 100644
--- a/compiler/rustc_mir_build/src/builder/coverageinfo.rs
+++ b/compiler/rustc_mir_build/src/builder/coverageinfo.rs
@@ -8,11 +8,8 @@ use rustc_middle::thir::{ExprId, ExprKind, Pat, Thir};
 use rustc_middle::ty::TyCtxt;
 use rustc_span::def_id::LocalDefId;
 
-use crate::builder::coverageinfo::mcdc::MCDCInfoBuilder;
 use crate::builder::{Builder, CFG};
 
-mod mcdc;
-
 /// Collects coverage-related information during MIR building, to eventually be
 /// turned into a function's [`CoverageInfoHi`] when MIR building is complete.
 pub(crate) struct CoverageInfoBuilder {
@@ -23,8 +20,6 @@ pub(crate) struct CoverageInfoBuilder {
 
     /// Present if branch coverage is enabled.
     branch_info: Option<BranchInfo>,
-    /// Present if MC/DC coverage is enabled.
-    mcdc_info: Option<MCDCInfoBuilder>,
 }
 
 #[derive(Default)]
@@ -83,7 +78,6 @@ impl CoverageInfoBuilder {
             nots: FxHashMap::default(),
             markers: BlockMarkerGen::default(),
             branch_info: tcx.sess.instrument_coverage_branch().then(BranchInfo::default),
-            mcdc_info: tcx.sess.instrument_coverage_mcdc().then(MCDCInfoBuilder::new),
         })
     }
 
@@ -135,26 +129,11 @@ impl CoverageInfoBuilder {
 
     fn register_two_way_branch<'tcx>(
         &mut self,
-        tcx: TyCtxt<'tcx>,
         cfg: &mut CFG<'tcx>,
         source_info: SourceInfo,
         true_block: BasicBlock,
         false_block: BasicBlock,
     ) {
-        // Separate path for handling branches when MC/DC is enabled.
-        if let Some(mcdc_info) = self.mcdc_info.as_mut() {
-            let inject_block_marker =
-                |source_info, block| self.markers.inject_block_marker(cfg, source_info, block);
-            mcdc_info.visit_evaluated_condition(
-                tcx,
-                source_info,
-                true_block,
-                false_block,
-                inject_block_marker,
-            );
-            return;
-        }
-
         // Bail out if branch coverage is not enabled.
         let Some(branch_info) = self.branch_info.as_mut() else { return };
 
@@ -169,23 +148,14 @@ impl CoverageInfoBuilder {
     }
 
     pub(crate) fn into_done(self) -> Box<CoverageInfoHi> {
-        let Self { nots: _, markers: BlockMarkerGen { num_block_markers }, branch_info, mcdc_info } =
-            self;
+        let Self { nots: _, markers: BlockMarkerGen { num_block_markers }, branch_info } = self;
 
         let branch_spans =
             branch_info.map(|branch_info| branch_info.branch_spans).unwrap_or_default();
 
-        let (mcdc_spans, mcdc_degraded_branch_spans) =
-            mcdc_info.map(MCDCInfoBuilder::into_done).unwrap_or_default();
-
         // For simplicity, always return an info struct (without Option), even
         // if there's nothing interesting in it.
-        Box::new(CoverageInfoHi {
-            num_block_markers,
-            branch_spans,
-            mcdc_degraded_branch_spans,
-            mcdc_spans,
-        })
+        Box::new(CoverageInfoHi { num_block_markers, branch_spans })
     }
 }
 
@@ -238,14 +208,7 @@ impl<'tcx> Builder<'_, 'tcx> {
             mir::TerminatorKind::if_(mir::Operand::Copy(place), true_block, false_block),
         );
 
-        // Separate path for handling branches when MC/DC is enabled.
-        coverage_info.register_two_way_branch(
-            self.tcx,
-            &mut self.cfg,
-            source_info,
-            true_block,
-            false_block,
-        );
+        coverage_info.register_two_way_branch(&mut self.cfg, source_info, true_block, false_block);
 
         let join_block = self.cfg.start_new_block();
         self.cfg.goto(true_block, source_info, join_block);
@@ -276,13 +239,7 @@ impl<'tcx> Builder<'_, 'tcx> {
 
         let source_info = SourceInfo { span: self.thir[expr_id].span, scope: self.source_scope };
 
-        coverage_info.register_two_way_branch(
-            self.tcx,
-            &mut self.cfg,
-            source_info,
-            then_block,
-            else_block,
-        );
+        coverage_info.register_two_way_branch(&mut self.cfg, source_info, then_block, else_block);
     }
 
     /// If branch coverage is enabled, inject marker statements into `true_block`
@@ -299,12 +256,6 @@ impl<'tcx> Builder<'_, 'tcx> {
         let Some(coverage_info) = self.coverage_info.as_mut() else { return };
 
         let source_info = SourceInfo { span: pattern.span, scope: self.source_scope };
-        coverage_info.register_two_way_branch(
-            self.tcx,
-            &mut self.cfg,
-            source_info,
-            true_block,
-            false_block,
-        );
+        coverage_info.register_two_way_branch(&mut self.cfg, source_info, true_block, false_block);
     }
 }
diff --git a/compiler/rustc_mir_build/src/builder/coverageinfo/mcdc.rs b/compiler/rustc_mir_build/src/builder/coverageinfo/mcdc.rs
deleted file mode 100644
index 6b4871dc1fc..00000000000
--- a/compiler/rustc_mir_build/src/builder/coverageinfo/mcdc.rs
+++ /dev/null
@@ -1,295 +0,0 @@
-use std::collections::VecDeque;
-
-use rustc_middle::bug;
-use rustc_middle::mir::coverage::{
-    BlockMarkerId, ConditionId, ConditionInfo, MCDCBranchSpan, MCDCDecisionSpan,
-};
-use rustc_middle::mir::{BasicBlock, SourceInfo};
-use rustc_middle::thir::LogicalOp;
-use rustc_middle::ty::TyCtxt;
-use rustc_span::Span;
-
-use crate::builder::Builder;
-use crate::errors::MCDCExceedsConditionLimit;
-
-/// LLVM uses `i16` to represent condition id. Hence `i16::MAX` is the hard limit for number of
-/// conditions in a decision.
-const MAX_CONDITIONS_IN_DECISION: usize = i16::MAX as usize;
-
-#[derive(Default)]
-struct MCDCDecisionCtx {
-    /// To construct condition evaluation tree.
-    decision_stack: VecDeque<ConditionInfo>,
-    processing_decision: Option<MCDCDecisionSpan>,
-    conditions: Vec<MCDCBranchSpan>,
-}
-
-struct MCDCState {
-    decision_ctx_stack: Vec<MCDCDecisionCtx>,
-}
-
-impl MCDCState {
-    fn new() -> Self {
-        Self { decision_ctx_stack: vec![MCDCDecisionCtx::default()] }
-    }
-
-    /// Decision depth is given as a u16 to reduce the size of the `CoverageKind`,
-    /// as it is very unlikely that the depth ever reaches 2^16.
-    #[inline]
-    fn decision_depth(&self) -> u16 {
-        match u16::try_from(self.decision_ctx_stack.len())
-            .expect(
-                "decision depth did not fit in u16, this is likely to be an instrumentation error",
-            )
-            .checked_sub(1)
-        {
-            Some(d) => d,
-            None => bug!("Unexpected empty decision stack"),
-        }
-    }
-
-    // At first we assign ConditionIds for each sub expression.
-    // If the sub expression is composite, re-assign its ConditionId to its LHS and generate a new ConditionId for its RHS.
-    //
-    // Example: "x = (A && B) || (C && D) || (D && F)"
-    //
-    //      Visit Depth1:
-    //              (A && B) || (C && D) || (D && F)
-    //              ^-------LHS--------^    ^-RHS--^
-    //                      ID=1              ID=2
-    //
-    //      Visit LHS-Depth2:
-    //              (A && B) || (C && D)
-    //              ^-LHS--^    ^-RHS--^
-    //                ID=1        ID=3
-    //
-    //      Visit LHS-Depth3:
-    //               (A && B)
-    //               LHS   RHS
-    //               ID=1  ID=4
-    //
-    //      Visit RHS-Depth3:
-    //                         (C && D)
-    //                         LHS   RHS
-    //                         ID=3  ID=5
-    //
-    //      Visit RHS-Depth2:              (D && F)
-    //                                     LHS   RHS
-    //                                     ID=2  ID=6
-    //
-    //      Visit Depth1:
-    //              (A && B)  || (C && D)  || (D && F)
-    //              ID=1  ID=4   ID=3  ID=5   ID=2  ID=6
-    //
-    // A node ID of '0' always means MC/DC isn't being tracked.
-    //
-    // If a "next" node ID is '0', it means it's the end of the test vector.
-    //
-    // As the compiler tracks expression in pre-order, we can ensure that condition info of parents are always properly assigned when their children are visited.
-    // - If the op is AND, the "false_next" of LHS and RHS should be the parent's "false_next". While "true_next" of the LHS is the RHS, the "true next" of RHS is the parent's "true_next".
-    // - If the op is OR, the "true_next" of LHS and RHS should be the parent's "true_next". While "false_next" of the LHS is the RHS, the "false next" of RHS is the parent's "false_next".
-    fn record_conditions(&mut self, op: LogicalOp, span: Span) {
-        let decision_depth = self.decision_depth();
-        let Some(decision_ctx) = self.decision_ctx_stack.last_mut() else {
-            bug!("Unexpected empty decision_ctx_stack")
-        };
-        let decision = match decision_ctx.processing_decision.as_mut() {
-            Some(decision) => {
-                decision.span = decision.span.to(span);
-                decision
-            }
-            None => decision_ctx.processing_decision.insert(MCDCDecisionSpan {
-                span,
-                num_conditions: 0,
-                end_markers: vec![],
-                decision_depth,
-            }),
-        };
-
-        let parent_condition = decision_ctx.decision_stack.pop_back().unwrap_or_else(|| {
-            assert_eq!(
-                decision.num_conditions, 0,
-                "decision stack must be empty only for empty decision"
-            );
-            decision.num_conditions += 1;
-            ConditionInfo {
-                condition_id: ConditionId::START,
-                true_next_id: None,
-                false_next_id: None,
-            }
-        });
-        let lhs_id = parent_condition.condition_id;
-
-        let rhs_condition_id = ConditionId::from(decision.num_conditions);
-        decision.num_conditions += 1;
-        let (lhs, rhs) = match op {
-            LogicalOp::And => {
-                let lhs = ConditionInfo {
-                    condition_id: lhs_id,
-                    true_next_id: Some(rhs_condition_id),
-                    false_next_id: parent_condition.false_next_id,
-                };
-                let rhs = ConditionInfo {
-                    condition_id: rhs_condition_id,
-                    true_next_id: parent_condition.true_next_id,
-                    false_next_id: parent_condition.false_next_id,
-                };
-                (lhs, rhs)
-            }
-            LogicalOp::Or => {
-                let lhs = ConditionInfo {
-                    condition_id: lhs_id,
-                    true_next_id: parent_condition.true_next_id,
-                    false_next_id: Some(rhs_condition_id),
-                };
-                let rhs = ConditionInfo {
-                    condition_id: rhs_condition_id,
-                    true_next_id: parent_condition.true_next_id,
-                    false_next_id: parent_condition.false_next_id,
-                };
-                (lhs, rhs)
-            }
-        };
-        // We visit expressions tree in pre-order, so place the left-hand side on the top.
-        decision_ctx.decision_stack.push_back(rhs);
-        decision_ctx.decision_stack.push_back(lhs);
-    }
-
-    fn try_finish_decision(
-        &mut self,
-        span: Span,
-        true_marker: BlockMarkerId,
-        false_marker: BlockMarkerId,
-        degraded_branches: &mut Vec<MCDCBranchSpan>,
-    ) -> Option<(MCDCDecisionSpan, Vec<MCDCBranchSpan>)> {
-        let Some(decision_ctx) = self.decision_ctx_stack.last_mut() else {
-            bug!("Unexpected empty decision_ctx_stack")
-        };
-        let Some(condition_info) = decision_ctx.decision_stack.pop_back() else {
-            let branch = MCDCBranchSpan {
-                span,
-                condition_info: ConditionInfo {
-                    condition_id: ConditionId::START,
-                    true_next_id: None,
-                    false_next_id: None,
-                },
-                true_marker,
-                false_marker,
-            };
-            degraded_branches.push(branch);
-            return None;
-        };
-        let Some(decision) = decision_ctx.processing_decision.as_mut() else {
-            bug!("Processing decision should have been created before any conditions are taken");
-        };
-        if condition_info.true_next_id.is_none() {
-            decision.end_markers.push(true_marker);
-        }
-        if condition_info.false_next_id.is_none() {
-            decision.end_markers.push(false_marker);
-        }
-        decision_ctx.conditions.push(MCDCBranchSpan {
-            span,
-            condition_info,
-            true_marker,
-            false_marker,
-        });
-
-        if decision_ctx.decision_stack.is_empty() {
-            let conditions = std::mem::take(&mut decision_ctx.conditions);
-            decision_ctx.processing_decision.take().map(|decision| (decision, conditions))
-        } else {
-            None
-        }
-    }
-}
-
-pub(crate) struct MCDCInfoBuilder {
-    degraded_spans: Vec<MCDCBranchSpan>,
-    mcdc_spans: Vec<(MCDCDecisionSpan, Vec<MCDCBranchSpan>)>,
-    state: MCDCState,
-}
-
-impl MCDCInfoBuilder {
-    pub(crate) fn new() -> Self {
-        Self { degraded_spans: vec![], mcdc_spans: vec![], state: MCDCState::new() }
-    }
-
-    pub(crate) fn visit_evaluated_condition(
-        &mut self,
-        tcx: TyCtxt<'_>,
-        source_info: SourceInfo,
-        true_block: BasicBlock,
-        false_block: BasicBlock,
-        mut inject_block_marker: impl FnMut(SourceInfo, BasicBlock) -> BlockMarkerId,
-    ) {
-        let true_marker = inject_block_marker(source_info, true_block);
-        let false_marker = inject_block_marker(source_info, false_block);
-
-        // take_condition() returns Some for decision_result when the decision stack
-        // is empty, i.e. when all the conditions of the decision were instrumented,
-        // and the decision is "complete".
-        if let Some((decision, conditions)) = self.state.try_finish_decision(
-            source_info.span,
-            true_marker,
-            false_marker,
-            &mut self.degraded_spans,
-        ) {
-            let num_conditions = conditions.len();
-            assert_eq!(
-                num_conditions, decision.num_conditions,
-                "final number of conditions is not correct"
-            );
-            match num_conditions {
-                0 => {
-                    unreachable!("Decision with no condition is not expected");
-                }
-                1..=MAX_CONDITIONS_IN_DECISION => {
-                    self.mcdc_spans.push((decision, conditions));
-                }
-                _ => {
-                    self.degraded_spans.extend(conditions);
-
-                    tcx.dcx().emit_warn(MCDCExceedsConditionLimit {
-                        span: decision.span,
-                        num_conditions,
-                        max_conditions: MAX_CONDITIONS_IN_DECISION,
-                    });
-                }
-            }
-        }
-    }
-
-    pub(crate) fn into_done(
-        self,
-    ) -> (Vec<(MCDCDecisionSpan, Vec<MCDCBranchSpan>)>, Vec<MCDCBranchSpan>) {
-        (self.mcdc_spans, self.degraded_spans)
-    }
-}
-
-impl Builder<'_, '_> {
-    pub(crate) fn visit_coverage_branch_operation(&mut self, logical_op: LogicalOp, span: Span) {
-        if let Some(coverage_info) = self.coverage_info.as_mut()
-            && let Some(mcdc_info) = coverage_info.mcdc_info.as_mut()
-        {
-            mcdc_info.state.record_conditions(logical_op, span);
-        }
-    }
-
-    pub(crate) fn mcdc_increment_depth_if_enabled(&mut self) {
-        if let Some(coverage_info) = self.coverage_info.as_mut()
-            && let Some(mcdc_info) = coverage_info.mcdc_info.as_mut()
-        {
-            mcdc_info.state.decision_ctx_stack.push(MCDCDecisionCtx::default());
-        };
-    }
-
-    pub(crate) fn mcdc_decrement_depth_if_enabled(&mut self) {
-        if let Some(coverage_info) = self.coverage_info.as_mut()
-            && let Some(mcdc_info) = coverage_info.mcdc_info.as_mut()
-            && mcdc_info.state.decision_ctx_stack.pop().is_none()
-        {
-            bug!("Unexpected empty decision stack");
-        };
-    }
-}
diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs
index 82b883a99a1..eb99c184bd2 100644
--- a/compiler/rustc_mir_build/src/builder/expr/into.rs
+++ b/compiler/rustc_mir_build/src/builder/expr/into.rs
@@ -159,8 +159,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let condition_scope = this.local_scope();
                 let source_info = this.source_info(expr.span);
 
-                this.visit_coverage_branch_operation(op, expr.span);
-
                 // We first evaluate the left-hand side of the predicate ...
                 let (then_block, else_block) =
                     this.in_if_then_scope(condition_scope, expr.span, |this| {
diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs
index 2c29b862841..9cdfb863330 100644
--- a/compiler/rustc_mir_build/src/builder/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs
@@ -125,15 +125,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let expr_span = expr.span;
 
         match expr.kind {
-            ExprKind::LogicalOp { op: op @ LogicalOp::And, lhs, rhs } => {
-                this.visit_coverage_branch_operation(op, expr_span);
+            ExprKind::LogicalOp { op: LogicalOp::And, lhs, rhs } => {
                 let lhs_then_block = this.then_else_break_inner(block, lhs, args).into_block();
                 let rhs_then_block =
                     this.then_else_break_inner(lhs_then_block, rhs, args).into_block();
                 rhs_then_block.unit()
             }
-            ExprKind::LogicalOp { op: op @ LogicalOp::Or, lhs, rhs } => {
-                this.visit_coverage_branch_operation(op, expr_span);
+            ExprKind::LogicalOp { op: LogicalOp::Or, lhs, rhs } => {
                 let local_scope = this.local_scope();
                 let (lhs_success_block, failure_block) =
                     this.in_if_then_scope(local_scope, expr_span, |this| {
@@ -214,9 +212,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let temp_scope = args.temp_scope_override.unwrap_or_else(|| this.local_scope());
                 let mutability = Mutability::Mut;
 
-                // Increment the decision depth, in case we encounter boolean expressions
-                // further down.
-                this.mcdc_increment_depth_if_enabled();
                 let place = unpack!(
                     block = this.as_temp(
                         block,
@@ -228,7 +223,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         mutability
                     )
                 );
-                this.mcdc_decrement_depth_if_enabled();
 
                 let operand = Operand::Move(Place::from(place));
 
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index 1a52c6c85cb..58c3de4a8b5 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -976,15 +976,6 @@ pub(crate) struct NonEmptyNeverPattern<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_exceeds_mcdc_condition_limit)]
-pub(crate) struct MCDCExceedsConditionLimit {
-    #[primary_span]
-    pub(crate) span: Span,
-    pub(crate) num_conditions: usize,
-    pub(crate) max_conditions: usize,
-}
-
-#[derive(Diagnostic)]
 #[diag(mir_build_pattern_not_covered, code = E0005)]
 pub(crate) struct PatternNotCovered<'s, 'tcx> {
     #[primary_span]