From c7ae4c2cb6d7e58ad0f9c12047e3d747c26a9d71 Mon Sep 17 00:00:00 2001 From: Rich Kadel Date: Fri, 23 Oct 2020 00:45:07 -0700 Subject: Splitting transform/instrument_coverage.rs into transform/coverage/... --- compiler/rustc_mir/src/transform/coverage/debug.rs | 70 ++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 compiler/rustc_mir/src/transform/coverage/debug.rs (limited to 'compiler/rustc_mir/src/transform/coverage/debug.rs') diff --git a/compiler/rustc_mir/src/transform/coverage/debug.rs b/compiler/rustc_mir/src/transform/coverage/debug.rs new file mode 100644 index 00000000000..0cd2e413da9 --- /dev/null +++ b/compiler/rustc_mir/src/transform/coverage/debug.rs @@ -0,0 +1,70 @@ +use super::graph::BasicCoverageBlocks; +use super::spans::CoverageSpan; + +use crate::util::pretty; +use crate::util::spanview::{self, SpanViewable}; + +use rustc_middle::mir::{self, TerminatorKind}; +use rustc_middle::ty::TyCtxt; + +/// Generates the MIR pass `CoverageSpan`-specific spanview dump file. +pub(crate) fn dump_coverage_spanview( + tcx: TyCtxt<'tcx>, + mir_body: &mir::Body<'tcx>, + basic_coverage_blocks: &BasicCoverageBlocks, + pass_name: &str, + coverage_spans: &Vec, +) { + let mir_source = mir_body.source; + let def_id = mir_source.def_id(); + + let span_viewables = span_viewables(tcx, mir_body, basic_coverage_blocks, &coverage_spans); + let mut file = pretty::create_dump_file(tcx, "html", None, pass_name, &0, mir_source) + .expect("Unexpected error creating MIR spanview HTML file"); + let crate_name = tcx.crate_name(def_id.krate); + let item_name = tcx.def_path(def_id).to_filename_friendly_no_crate(); + let title = format!("{}.{} - Coverage Spans", crate_name, item_name); + spanview::write_document(tcx, def_id, span_viewables, &title, &mut file) + .expect("Unexpected IO error dumping coverage spans as HTML"); +} + +/// Converts the computed `BasicCoverageBlock`s into `SpanViewable`s. +fn span_viewables( + tcx: TyCtxt<'tcx>, + mir_body: &mir::Body<'tcx>, + basic_coverage_blocks: &BasicCoverageBlocks, + coverage_spans: &Vec, +) -> Vec { + let mut span_viewables = Vec::new(); + for coverage_span in coverage_spans { + let tooltip = coverage_span.format_coverage_statements(tcx, mir_body); + let CoverageSpan { span, bcb_leader_bb: bb, .. } = coverage_span; + let bcb = &basic_coverage_blocks[*bb]; + let id = bcb.id(); + let leader_bb = bcb.leader_bb(); + span_viewables.push(SpanViewable { bb: leader_bb, span: *span, id, tooltip }); + } + span_viewables +} + +/// Returns a simple string representation of a `TerminatorKind` variant, indenpendent of any +/// values it might hold. +pub(crate) fn term_type(kind: &TerminatorKind<'tcx>) -> &'static str { + match kind { + TerminatorKind::Goto { .. } => "Goto", + TerminatorKind::SwitchInt { .. } => "SwitchInt", + TerminatorKind::Resume => "Resume", + TerminatorKind::Abort => "Abort", + TerminatorKind::Return => "Return", + TerminatorKind::Unreachable => "Unreachable", + TerminatorKind::Drop { .. } => "Drop", + TerminatorKind::DropAndReplace { .. } => "DropAndReplace", + TerminatorKind::Call { .. } => "Call", + TerminatorKind::Assert { .. } => "Assert", + TerminatorKind::Yield { .. } => "Yield", + TerminatorKind::GeneratorDrop => "GeneratorDrop", + TerminatorKind::FalseEdge { .. } => "FalseEdge", + TerminatorKind::FalseUnwind { .. } => "FalseUnwind", + TerminatorKind::InlineAsm { .. } => "InlineAsm", + } +} -- cgit 1.4.1-3-g733a5 From b5020648fe294a1f139586e4243903d8c1a105b8 Mon Sep 17 00:00:00 2001 From: Rich Kadel Date: Thu, 22 Oct 2020 23:11:38 -0700 Subject: Implemented CoverageGraph of BasicCoverageBlocks --- compiler/rustc_mir/src/transform/coverage/debug.rs | 16 +- compiler/rustc_mir/src/transform/coverage/graph.rs | 458 ++++++++++++++------- compiler/rustc_mir/src/transform/coverage/mod.rs | 21 +- compiler/rustc_mir/src/transform/coverage/spans.rs | 51 ++- .../expected_export_coverage.lazy_boolean.json | 20 +- ...xpected_export_coverage.loops_and_branches.json | 12 +- .../expected_export_coverage.nested_loops.json | 20 +- .../expected_export_coverage.try_error_result.json | 24 +- .../expected_export_coverage.while.json | 12 +- ...xpected_export_coverage.while_early_return.json | 20 +- .../expected_show_coverage.lazy_boolean.txt | 4 +- .../expected_show_coverage.nested_loops.txt | 4 +- .../expected_show_coverage.try_error_result.txt | 4 +- .../expected_show_coverage.while_early_return.txt | 2 +- .../expected_show_coverage_counters.drop_trait.txt | 5 +- .../expected_show_coverage_counters.generics.txt | 5 +- .../expected_show_coverage_counters.if_else.txt | 9 +- ...xpected_show_coverage_counters.lazy_boolean.txt | 10 +- ...d_show_coverage_counters.loops_and_branches.txt | 1 - ...xpected_show_coverage_counters.nested_loops.txt | 10 +- ...ted_show_coverage_counters.try_error_result.txt | 9 +- .../expected_show_coverage_counters.while.txt | 5 +- ...d_show_coverage_counters.while_early_return.txt | 4 - .../expected_export_coverage.lazy_boolean.json | 20 +- ...xpected_export_coverage.loops_and_branches.json | 12 +- .../expected_export_coverage.nested_loops.json | 20 +- .../expected_export_coverage.try_error_result.json | 24 +- .../expected_export_coverage.while.json | 12 +- ...xpected_export_coverage.while_early_return.json | 20 +- .../expected_show_coverage.lazy_boolean.txt | 4 +- .../expected_show_coverage.nested_loops.txt | 4 +- .../expected_show_coverage.try_error_result.txt | 4 +- .../expected_show_coverage.while_early_return.txt | 2 +- .../expected_show_coverage_counters.drop_trait.txt | 5 +- .../expected_show_coverage_counters.generics.txt | 5 +- .../expected_show_coverage_counters.if_else.txt | 9 +- ...xpected_show_coverage_counters.lazy_boolean.txt | 10 +- ...d_show_coverage_counters.loops_and_branches.txt | 1 - ...xpected_show_coverage_counters.nested_loops.txt | 10 +- ..._counters.partial_eq_counter_without_region.txt | 6 +- ...ted_show_coverage_counters.try_error_result.txt | 9 +- .../expected_show_coverage_counters.while.txt | 5 +- ...d_show_coverage_counters.while_early_return.txt | 4 - ..._boolean.main.-------.InstrumentCoverage.0.html | 28 +- ....{impl#0}-fmt.-------.InstrumentCoverage.0.html | 2 +- ...ed_loops.main.-------.InstrumentCoverage.0.html | 6 +- ....{impl#1}-cmp.-------.InstrumentCoverage.0.html | 6 +- ...}-partial_cmp.-------.InstrumentCoverage.0.html | 6 +- ...ite_loop.main.-------.InstrumentCoverage.0.html | 4 +- ...r_result.main.-------.InstrumentCoverage.0.html | 6 +- .../while.main.-------.InstrumentCoverage.0.html | 2 +- ...y_return.main.-------.InstrumentCoverage.0.html | 12 +- ..._boolean.main.-------.InstrumentCoverage.0.html | 28 +- ....{impl#0}-fmt.-------.InstrumentCoverage.0.html | 2 +- ...ed_loops.main.-------.InstrumentCoverage.0.html | 6 +- ....{impl#1}-cmp.-------.InstrumentCoverage.0.html | 6 +- ...}-partial_cmp.-------.InstrumentCoverage.0.html | 6 +- ...ite_loop.main.-------.InstrumentCoverage.0.html | 4 +- ...r_result.main.-------.InstrumentCoverage.0.html | 6 +- .../while.main.-------.InstrumentCoverage.0.html | 2 +- ...y_return.main.-------.InstrumentCoverage.0.html | 12 +- 61 files changed, 563 insertions(+), 493 deletions(-) (limited to 'compiler/rustc_mir/src/transform/coverage/debug.rs') diff --git a/compiler/rustc_mir/src/transform/coverage/debug.rs b/compiler/rustc_mir/src/transform/coverage/debug.rs index 0cd2e413da9..7eb2d33453c 100644 --- a/compiler/rustc_mir/src/transform/coverage/debug.rs +++ b/compiler/rustc_mir/src/transform/coverage/debug.rs @@ -1,4 +1,4 @@ -use super::graph::BasicCoverageBlocks; +use super::graph::CoverageGraph; use super::spans::CoverageSpan; use crate::util::pretty; @@ -11,7 +11,7 @@ use rustc_middle::ty::TyCtxt; pub(crate) fn dump_coverage_spanview( tcx: TyCtxt<'tcx>, mir_body: &mir::Body<'tcx>, - basic_coverage_blocks: &BasicCoverageBlocks, + basic_coverage_blocks: &CoverageGraph, pass_name: &str, coverage_spans: &Vec, ) { @@ -28,20 +28,20 @@ pub(crate) fn dump_coverage_spanview( .expect("Unexpected IO error dumping coverage spans as HTML"); } -/// Converts the computed `BasicCoverageBlock`s into `SpanViewable`s. +/// Converts the computed `BasicCoverageBlockData`s into `SpanViewable`s. fn span_viewables( tcx: TyCtxt<'tcx>, mir_body: &mir::Body<'tcx>, - basic_coverage_blocks: &BasicCoverageBlocks, + basic_coverage_blocks: &CoverageGraph, coverage_spans: &Vec, ) -> Vec { let mut span_viewables = Vec::new(); for coverage_span in coverage_spans { let tooltip = coverage_span.format_coverage_statements(tcx, mir_body); - let CoverageSpan { span, bcb_leader_bb: bb, .. } = coverage_span; - let bcb = &basic_coverage_blocks[*bb]; - let id = bcb.id(); - let leader_bb = bcb.leader_bb(); + let CoverageSpan { span, bcb, .. } = coverage_span; + let bcb_data = &basic_coverage_blocks[*bcb]; + let id = bcb_data.id(); + let leader_bb = bcb_data.leader_bb(); span_viewables.push(SpanViewable { bb: leader_bb, span: *span, id, tooltip }); } span_viewables diff --git a/compiler/rustc_mir/src/transform/coverage/graph.rs b/compiler/rustc_mir/src/transform/coverage/graph.rs index c0a698833a1..3d3e76f907b 100644 --- a/compiler/rustc_mir/src/transform/coverage/graph.rs +++ b/compiler/rustc_mir/src/transform/coverage/graph.rs @@ -1,152 +1,100 @@ +use rustc_data_structures::graph::dominators::{self, Dominators}; +use rustc_data_structures::graph::{self, GraphSuccessors, WithNumNodes}; use rustc_index::bit_set::BitSet; use rustc_index::vec::IndexVec; -use rustc_middle::mir::{self, BasicBlock, BasicBlockData, TerminatorKind}; +use rustc_middle::mir::{self, BasicBlock, BasicBlockData, Terminator, TerminatorKind}; + +use std::ops::{Index, IndexMut}; const ID_SEPARATOR: &str = ","; -/// A BasicCoverageBlock (BCB) represents the maximal-length sequence of CFG (MIR) BasicBlocks -/// without conditional branches. -/// -/// The BCB allows coverage analysis to be performed on a simplified projection of the underlying -/// MIR CFG, without altering the original CFG. Note that running the MIR `SimplifyCfg` transform, -/// is not sufficient, and therefore not necessary, since the BCB-based CFG projection is a more -/// aggressive simplification. For example: -/// -/// * The BCB CFG projection ignores (trims) branches not relevant to coverage, such as unwind- -/// related code that is injected by the Rust compiler but has no physical source code to -/// count. This also means a BasicBlock with a `Call` terminator can be merged into its -/// primary successor target block, in the same BCB. -/// * Some BasicBlock terminators support Rust-specific concerns--like borrow-checking--that are -/// not relevant to coverage analysis. `FalseUnwind`, for example, can be treated the same as -/// a `Goto`, and merged with its successor into the same BCB. -/// -/// Each BCB with at least one computed `CoverageSpan` will have no more than one `Counter`. -/// In some cases, a BCB's execution count can be computed by `CounterExpression`. Additional -/// disjoint `CoverageSpan`s in a BCB can also be counted by `CounterExpression` (by adding `ZERO` -/// to the BCB's primary counter or expression). -/// -/// Dominator/dominated relationships (which are fundamental to the coverage analysis algorithm) -/// between two BCBs can be computed using the `mir::Body` `dominators()` with any `BasicBlock` -/// member of each BCB. (For consistency, BCB's use the first `BasicBlock`, also referred to as the -/// `bcb_leader_bb`.) -/// -/// The BCB CFG projection is critical to simplifying the coverage analysis by ensuring graph -/// path-based queries (`is_dominated_by()`, `predecessors`, `successors`, etc.) have branch -/// (control flow) significance. -#[derive(Debug, Clone)] -pub(crate) struct BasicCoverageBlock { - pub blocks: Vec, +/// A coverage-specific simplification of the MIR control flow graph (CFG). The `CoverageGraph`s +/// nodes are `BasicCoverageBlock`s, which encompass one or more MIR `BasicBlock`s, plus a +/// `CoverageKind` counter (to be added by `CoverageCounters::make_bcb_counters`), and an optional +/// set of additional counters--if needed--to count incoming edges, if there are more than one. +/// (These "edge counters" are eventually converted into new MIR `BasicBlock`s.) +pub(crate) struct CoverageGraph { + bcbs: IndexVec, + bb_to_bcb: IndexVec>, + pub successors: IndexVec>, + pub predecessors: IndexVec>, + dominators: Option>, } -impl BasicCoverageBlock { - pub fn leader_bb(&self) -> BasicBlock { - self.blocks[0] - } +impl CoverageGraph { + pub fn from_mir(mir_body: &mir::Body<'tcx>) -> Self { + let (bcbs, bb_to_bcb) = Self::compute_basic_coverage_blocks(mir_body); - pub fn id(&self) -> String { - format!( - "@{}", - self.blocks - .iter() - .map(|bb| bb.index().to_string()) - .collect::>() - .join(ID_SEPARATOR) - ) - } -} + // Pre-transform MIR `BasicBlock` successors and predecessors into the BasicCoverageBlock + // equivalents. Note that since the BasicCoverageBlock graph has been fully simplified, the + // each predecessor of a BCB leader_bb should be in a unique BCB, and each successor of a + // BCB last_bb should bin in its own unique BCB. Therefore, collecting the BCBs using + // `bb_to_bcb` should work without requiring a deduplication step. -pub(crate) struct BasicCoverageBlocks { - vec: IndexVec>, -} + let successors = IndexVec::from_fn_n( + |bcb| { + let bcb_data = &bcbs[bcb]; + let bcb_successors = + bcb_filtered_successors(&mir_body, &bcb_data.terminator(mir_body).kind) + .filter_map(|&successor_bb| bb_to_bcb[successor_bb]) + .collect::>(); + debug_assert!({ + let mut sorted = bcb_successors.clone(); + sorted.sort_unstable(); + let initial_len = sorted.len(); + sorted.dedup(); + sorted.len() == initial_len + }); + bcb_successors + }, + bcbs.len(), + ); + + let mut predecessors = IndexVec::from_elem_n(Vec::new(), bcbs.len()); + for (bcb, bcb_successors) in successors.iter_enumerated() { + for &successor in bcb_successors { + predecessors[successor].push(bcb); + } + } -impl BasicCoverageBlocks { - pub fn from_mir(mir_body: &mir::Body<'tcx>) -> Self { let mut basic_coverage_blocks = - BasicCoverageBlocks { vec: IndexVec::from_elem_n(None, mir_body.basic_blocks().len()) }; - basic_coverage_blocks.extract_from_mir(mir_body); + Self { bcbs, bb_to_bcb, successors, predecessors, dominators: None }; + let dominators = dominators::dominators(&basic_coverage_blocks); + basic_coverage_blocks.dominators = Some(dominators); basic_coverage_blocks } - pub fn iter(&self) -> impl Iterator { - self.vec.iter().filter_map(|bcb| bcb.as_ref()) - } - - pub fn num_nodes(&self) -> usize { - self.vec.len() - } - - pub fn extract_from_mir(&mut self, mir_body: &mir::Body<'tcx>) { - // Traverse the CFG but ignore anything following an `unwind` - let cfg_without_unwind = ShortCircuitPreorder::new(&mir_body, |term_kind| { - let mut successors = term_kind.successors(); - match &term_kind { - // SwitchInt successors are never unwind, and all of them should be traversed. - - // NOTE: TerminatorKind::FalseEdge targets from SwitchInt don't appear to be - // helpful in identifying unreachable code. I did test the theory, but the following - // changes were not beneficial. (I assumed that replacing some constants with - // non-deterministic variables might effect which blocks were targeted by a - // `FalseEdge` `imaginary_target`. It did not.) - // - // Also note that, if there is a way to identify BasicBlocks that are part of the - // MIR CFG, but not actually reachable, here are some other things to consider: - // - // Injecting unreachable code regions will probably require computing the set - // difference between the basic blocks found without filtering out unreachable - // blocks, and the basic blocks found with the filter; then computing the - // `CoverageSpans` without the filter; and then injecting `Counter`s or - // `CounterExpression`s for blocks that are not unreachable, or injecting - // `Unreachable` code regions otherwise. This seems straightforward, but not - // trivial. - // - // Alternatively, we might instead want to leave the unreachable blocks in - // (bypass the filter here), and inject the counters. This will result in counter - // values of zero (0) for unreachable code (and, notably, the code will be displayed - // with a red background by `llvm-cov show`). - // - // TerminatorKind::SwitchInt { .. } => { - // let some_imaginary_target = successors.clone().find_map(|&successor| { - // let term = mir_body.basic_blocks()[successor].terminator(); - // if let TerminatorKind::FalseEdge { imaginary_target, .. } = term.kind { - // if mir_body.predecessors()[imaginary_target].len() == 1 { - // return Some(imaginary_target); - // } - // } - // None - // }); - // if let Some(imaginary_target) = some_imaginary_target { - // box successors.filter(move |&&successor| successor != imaginary_target) - // } else { - // box successors - // } - // } - // - // Note this also required changing the closure signature for the - // `ShortCurcuitPreorder` to: - // - // F: Fn(&'tcx TerminatorKind<'tcx>) -> Box + 'a>, - TerminatorKind::SwitchInt { .. } => successors, - - // For all other kinds, return only the first successor, if any, and ignore unwinds - _ => successors.next().into_iter().chain(&[]), - } - }); + fn compute_basic_coverage_blocks( + mir_body: &mir::Body<'tcx>, + ) -> ( + IndexVec, + IndexVec>, + ) { + let num_basic_blocks = mir_body.num_nodes(); + let mut bcbs = IndexVec::with_capacity(num_basic_blocks); + let mut bb_to_bcb = IndexVec::from_elem_n(None, num_basic_blocks); - // Walk the CFG using a Preorder traversal, which starts from `START_BLOCK` and follows + // Walk the MIR CFG using a Preorder traversal, which starts from `START_BLOCK` and follows // each block terminator's `successors()`. Coverage spans must map to actual source code, - // so compiler generated blocks and paths can be ignored. To that end the CFG traversal + // so compiler generated blocks and paths can be ignored. To that end, the CFG traversal // intentionally omits unwind paths. - let mut blocks = Vec::new(); - for (bb, data) in cfg_without_unwind { - if let Some(last) = blocks.last() { + let mir_cfg_without_unwind = ShortCircuitPreorder::new(&mir_body, bcb_filtered_successors); + + let mut basic_blocks = Vec::new(); + for (bb, data) in mir_cfg_without_unwind { + if let Some(last) = basic_blocks.last() { let predecessors = &mir_body.predecessors()[bb]; if predecessors.len() > 1 || !predecessors.contains(last) { // The `bb` has more than one _incoming_ edge, and should start its own - // `BasicCoverageBlock`. (Note, the `blocks` vector does not yet include `bb`; - // it contains a sequence of one or more sequential blocks with no intermediate - // branches in or out. Save these as a new `BasicCoverageBlock` before starting - // the new one.) - self.add_basic_coverage_block(blocks.split_off(0)); + // `BasicCoverageBlockData`. (Note, the `basic_blocks` vector does not yet + // include `bb`; it contains a sequence of one or more sequential basic_blocks + // with no intermediate branches in or out. Save these as a new + // `BasicCoverageBlockData` before starting the new one.) + Self::add_basic_coverage_block( + &mut bcbs, + &mut bb_to_bcb, + basic_blocks.split_off(0), + ); debug!( " because {}", if predecessors.len() > 1 { @@ -157,27 +105,40 @@ impl BasicCoverageBlocks { ); } } - blocks.push(bb); + basic_blocks.push(bb); let term = data.terminator(); match term.kind { TerminatorKind::Return { .. } + // FIXME(richkadel): Add test(s) for `Abort` coverage. | TerminatorKind::Abort + // FIXME(richkadel): Add test(s) for `Assert` coverage. + // Should `Assert` be handled like `FalseUnwind` instead? Since we filter out unwind + // branches when creating the BCB CFG, aren't `Assert`s (without unwinds) just like + // `FalseUnwinds` (which are kind of like `Goto`s)? | TerminatorKind::Assert { .. } + // FIXME(richkadel): Add test(s) for `Yield` coverage, and confirm coverage is + // sensible for code using the `yield` keyword. | TerminatorKind::Yield { .. } + // FIXME(richkadel): Also add coverage tests using async/await, and threading. + | TerminatorKind::SwitchInt { .. } => { // The `bb` has more than one _outgoing_ edge, or exits the function. Save the - // current sequence of `blocks` gathered to this point, as a new - // `BasicCoverageBlock`. - self.add_basic_coverage_block(blocks.split_off(0)); + // current sequence of `basic_blocks` gathered to this point, as a new + // `BasicCoverageBlockData`. + Self::add_basic_coverage_block( + &mut bcbs, + &mut bb_to_bcb, + basic_blocks.split_off(0), + ); debug!(" because term.kind = {:?}", term.kind); // Note that this condition is based on `TerminatorKind`, even though it // theoretically boils down to `successors().len() != 1`; that is, either zero // (e.g., `Return`, `Abort`) or multiple successors (e.g., `SwitchInt`), but - // since the Coverage graph (the BCB CFG projection) ignores things like unwind - // branches (which exist in the `Terminator`s `successors()` list) checking the - // number of successors won't work. + // since the BCB CFG ignores things like unwind branches (which exist in the + // `Terminator`s `successors()` list) checking the number of successors won't + // work. } TerminatorKind::Goto { .. } | TerminatorKind::Resume @@ -192,45 +153,222 @@ impl BasicCoverageBlocks { } } - if !blocks.is_empty() { - // process any remaining blocks into a final `BasicCoverageBlock` - self.add_basic_coverage_block(blocks.split_off(0)); - debug!(" because the end of the CFG was reached while traversing"); + if !basic_blocks.is_empty() { + // process any remaining basic_blocks into a final `BasicCoverageBlockData` + Self::add_basic_coverage_block(&mut bcbs, &mut bb_to_bcb, basic_blocks.split_off(0)); + debug!(" because the end of the MIR CFG was reached while traversing"); + } + + (bcbs, bb_to_bcb) + } + + fn add_basic_coverage_block( + bcbs: &mut IndexVec, + bb_to_bcb: &mut IndexVec>, + basic_blocks: Vec, + ) { + let bcb = BasicCoverageBlock::from_usize(bcbs.len()); + for &bb in basic_blocks.iter() { + bb_to_bcb[bb] = Some(bcb); } + let bcb_data = BasicCoverageBlockData::from(basic_blocks); + debug!("adding bcb{}: {:?}", bcb.index(), bcb_data); + bcbs.push(bcb_data); + } + + #[inline(always)] + pub fn iter_enumerated( + &self, + ) -> impl Iterator { + self.bcbs.iter_enumerated() + } + + #[inline(always)] + pub fn bcb_from_bb(&self, bb: BasicBlock) -> Option { + if bb.index() < self.bb_to_bcb.len() { self.bb_to_bcb[bb] } else { None } + } + + #[inline(always)] + pub fn is_dominated_by(&self, node: BasicCoverageBlock, dom: BasicCoverageBlock) -> bool { + self.dominators.as_ref().unwrap().is_dominated_by(node, dom) + } + + #[inline(always)] + pub fn dominators(&self) -> &Dominators { + self.dominators.as_ref().unwrap() + } +} + +impl Index for CoverageGraph { + type Output = BasicCoverageBlockData; + + #[inline] + fn index(&self, index: BasicCoverageBlock) -> &BasicCoverageBlockData { + &self.bcbs[index] + } +} + +impl IndexMut for CoverageGraph { + #[inline] + fn index_mut(&mut self, index: BasicCoverageBlock) -> &mut BasicCoverageBlockData { + &mut self.bcbs[index] + } +} + +impl graph::DirectedGraph for CoverageGraph { + type Node = BasicCoverageBlock; +} + +impl graph::WithNumNodes for CoverageGraph { + #[inline] + fn num_nodes(&self) -> usize { + self.bcbs.len() + } +} + +impl graph::WithStartNode for CoverageGraph { + #[inline] + fn start_node(&self) -> Self::Node { + self.bcb_from_bb(mir::START_BLOCK) + .expect("mir::START_BLOCK should be in a BasicCoverageBlock") + } +} + +type BcbSuccessors<'graph> = std::slice::Iter<'graph, BasicCoverageBlock>; + +impl<'graph> graph::GraphSuccessors<'graph> for CoverageGraph { + type Item = BasicCoverageBlock; + type Iter = std::iter::Cloned>; +} + +impl graph::WithSuccessors for CoverageGraph { + #[inline] + fn successors(&self, node: Self::Node) -> >::Iter { + self.successors[node].iter().cloned() + } +} + +impl graph::GraphPredecessors<'graph> for CoverageGraph { + type Item = BasicCoverageBlock; + type Iter = std::vec::IntoIter; +} + +impl graph::WithPredecessors for CoverageGraph { + #[inline] + fn predecessors(&self, node: Self::Node) -> >::Iter { + self.predecessors[node].clone().into_iter() } +} - fn add_basic_coverage_block(&mut self, blocks: Vec) { - let leader_bb = blocks[0]; - let bcb = BasicCoverageBlock { blocks }; - debug!("adding BCB: {:?}", bcb); - self.vec[leader_bb] = Some(bcb); +rustc_index::newtype_index! { + /// A node in the [control-flow graph][CFG] of CoverageGraph. + pub(crate) struct BasicCoverageBlock { + DEBUG_FORMAT = "bcb{}", } } -impl std::ops::Index for BasicCoverageBlocks { - type Output = BasicCoverageBlock; +/// A BasicCoverageBlockData (BCB) represents the maximal-length sequence of MIR BasicBlocks without +/// conditional branches, and form a new, simplified, coverage-specific Control Flow Graph, without +/// altering the original MIR CFG. +/// +/// Note that running the MIR `SimplifyCfg` transform is not sufficient (and therefore not +/// necessary). The BCB-based CFG is a more aggressive simplification. For example: +/// +/// * The BCB CFG ignores (trims) branches not relevant to coverage, such as unwind-related code, +/// that is injected by the Rust compiler but has no physical source code to count. This also +/// means a BasicBlock with a `Call` terminator can be merged into its primary successor target +/// block, in the same BCB. +/// * Some BasicBlock terminators support Rust-specific concerns--like borrow-checking--that are +/// not relevant to coverage analysis. `FalseUnwind`, for example, can be treated the same as +/// a `Goto`, and merged with its successor into the same BCB. +/// +/// Each BCB with at least one computed `CoverageSpan` will have no more than one `Counter`. +/// In some cases, a BCB's execution count can be computed by `Expression`. Additional +/// disjoint `CoverageSpan`s in a BCB can also be counted by `Expression` (by adding `ZERO` +/// to the BCB's primary counter or expression). +/// +/// The BCB CFG is critical to simplifying the coverage analysis by ensuring graph path-based +/// queries (`is_dominated_by()`, `predecessors`, `successors`, etc.) have branch (control flow) +/// significance. +#[derive(Debug, Clone)] +pub(crate) struct BasicCoverageBlockData { + pub basic_blocks: Vec, +} + +impl BasicCoverageBlockData { + pub fn from(basic_blocks: Vec) -> Self { + assert!(basic_blocks.len() > 0); + Self { basic_blocks } + } + + #[inline(always)] + pub fn leader_bb(&self) -> BasicBlock { + self.basic_blocks[0] + } + + #[inline(always)] + pub fn last_bb(&self) -> BasicBlock { + *self.basic_blocks.last().unwrap() + } + + #[inline(always)] + pub fn terminator<'a, 'tcx>(&self, mir_body: &'a mir::Body<'tcx>) -> &'a Terminator<'tcx> { + &mir_body[self.last_bb()].terminator() + } + + pub fn id(&self) -> String { + format!( + "@{}", + self.basic_blocks + .iter() + .map(|bb| bb.index().to_string()) + .collect::>() + .join(ID_SEPARATOR) + ) + } +} - fn index(&self, index: BasicBlock) -> &Self::Output { - self.vec[index].as_ref().expect("is_some if BasicBlock is a BasicCoverageBlock leader") +fn bcb_filtered_successors<'a, 'tcx>( + body: &'tcx &'a mir::Body<'tcx>, + term_kind: &'tcx TerminatorKind<'tcx>, +) -> Box + 'a> { + let mut successors = term_kind.successors(); + box match &term_kind { + // SwitchInt successors are never unwind, and all of them should be traversed. + TerminatorKind::SwitchInt { .. } => successors, + // For all other kinds, return only the first successor, if any, and ignore unwinds. + // NOTE: `chain(&[])` is required to coerce the `option::iter` (from + // `next().into_iter()`) into the `mir::Successors` aliased type. + _ => successors.next().into_iter().chain(&[]), } + .filter(move |&&successor| body[successor].terminator().kind != TerminatorKind::Unreachable) } pub struct ShortCircuitPreorder< 'a, 'tcx, - F: Fn(&'tcx TerminatorKind<'tcx>) -> mir::Successors<'tcx>, + F: Fn( + &'tcx &'a mir::Body<'tcx>, + &'tcx TerminatorKind<'tcx>, + ) -> Box + 'a>, > { - body: &'a mir::Body<'tcx>, + body: &'tcx &'a mir::Body<'tcx>, visited: BitSet, worklist: Vec, filtered_successors: F, } -impl<'a, 'tcx, F: Fn(&'tcx TerminatorKind<'tcx>) -> mir::Successors<'tcx>> - ShortCircuitPreorder<'a, 'tcx, F> +impl< + 'a, + 'tcx, + F: Fn( + &'tcx &'a mir::Body<'tcx>, + &'tcx TerminatorKind<'tcx>, + ) -> Box + 'a>, +> ShortCircuitPreorder<'a, 'tcx, F> { pub fn new( - body: &'a mir::Body<'tcx>, + body: &'tcx &'a mir::Body<'tcx>, filtered_successors: F, ) -> ShortCircuitPreorder<'a, 'tcx, F> { let worklist = vec![mir::START_BLOCK]; @@ -244,8 +382,14 @@ impl<'a, 'tcx, F: Fn(&'tcx TerminatorKind<'tcx>) -> mir::Successors<'tcx>> } } -impl<'a: 'tcx, 'tcx, F: Fn(&'tcx TerminatorKind<'tcx>) -> mir::Successors<'tcx>> Iterator - for ShortCircuitPreorder<'a, 'tcx, F> +impl< + 'a: 'tcx, + 'tcx, + F: Fn( + &'tcx &'a mir::Body<'tcx>, + &'tcx TerminatorKind<'tcx>, + ) -> Box + 'a>, +> Iterator for ShortCircuitPreorder<'a, 'tcx, F> { type Item = (BasicBlock, &'a BasicBlockData<'tcx>); @@ -258,7 +402,7 @@ impl<'a: 'tcx, 'tcx, F: Fn(&'tcx TerminatorKind<'tcx>) -> mir::Successors<'tcx>> let data = &self.body[idx]; if let Some(ref term) = data.terminator { - self.worklist.extend((self.filtered_successors)(&term.kind)); + self.worklist.extend((self.filtered_successors)(&self.body, &term.kind)); } return Some((idx, data)); diff --git a/compiler/rustc_mir/src/transform/coverage/mod.rs b/compiler/rustc_mir/src/transform/coverage/mod.rs index 9961afba8e7..aa5771cfad4 100644 --- a/compiler/rustc_mir/src/transform/coverage/mod.rs +++ b/compiler/rustc_mir/src/transform/coverage/mod.rs @@ -6,13 +6,14 @@ mod graph; mod spans; use counters::CoverageCounters; -use graph::BasicCoverageBlocks; +use graph::CoverageGraph; use spans::{CoverageSpan, CoverageSpans}; use crate::transform::MirPass; use crate::util::pretty; use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::graph::WithNumNodes; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; use rustc_index::vec::IndexVec; @@ -73,7 +74,7 @@ struct Instrumentor<'a, 'tcx> { tcx: TyCtxt<'tcx>, mir_body: &'a mut mir::Body<'tcx>, body_span: Span, - basic_coverage_blocks: BasicCoverageBlocks, + basic_coverage_blocks: CoverageGraph, coverage_counters: CoverageCounters, } @@ -82,7 +83,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { let hir_body = hir_body(tcx, mir_body.source.def_id()); let body_span = hir_body.value.span; let function_source_hash = hash_mir_source(tcx, hir_body); - let basic_coverage_blocks = BasicCoverageBlocks::from_mir(mir_body); + let basic_coverage_blocks = CoverageGraph::from_mir(mir_body); Self { pass_name, tcx, @@ -103,7 +104,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { debug!("instrumenting {:?}, span: {}", def_id, source_map.span_to_string(body_span)); //////////////////////////////////////////////////// - // Compute `CoverageSpan`s from the `BasicCoverageBlocks`. + // Compute `CoverageSpan`s from the `CoverageGraph`. let coverage_spans = CoverageSpans::generate_coverage_spans( &self.mir_body, body_span, @@ -135,9 +136,11 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { let source_file = source_map.lookup_source_file(body_span.lo()); let file_name = Symbol::intern(&source_file.name.to_string()); - let mut bb_counters = IndexVec::from_elem_n(None, self.mir_body.basic_blocks().len()); - for CoverageSpan { span, bcb_leader_bb: bb, .. } in coverage_spans { - if let Some(&counter_operand) = bb_counters[bb].as_ref() { + let mut bcb_counters = IndexVec::from_elem_n(None, self.basic_coverage_blocks.num_nodes()); + for covspan in coverage_spans { + let bcb = covspan.bcb; + let span = covspan.span; + if let Some(&counter_operand) = bcb_counters[bcb].as_ref() { let expression = self.coverage_counters.make_expression( counter_operand, Op::Add, @@ -149,6 +152,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { span, source_map.span_to_snippet(span).expect("Error getting source for span"), ); + let bb = self.basic_coverage_blocks[bcb].leader_bb(); let code_region = make_code_region(file_name, &source_file, span, body_span); inject_statement(self.mir_body, expression, bb, Some(code_region)); } else { @@ -160,7 +164,8 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { source_map.span_to_snippet(span).expect("Error getting source for span"), ); let counter_operand = counter.as_operand_id(); - bb_counters[bb] = Some(counter_operand); + bcb_counters[bcb] = Some(counter_operand); + let bb = self.basic_coverage_blocks[bcb].leader_bb(); let code_region = make_code_region(file_name, &source_file, span, body_span); inject_statement(self.mir_body, counter, bb, Some(code_region)); } diff --git a/compiler/rustc_mir/src/transform/coverage/spans.rs b/compiler/rustc_mir/src/transform/coverage/spans.rs index 7957b6f3ff5..23531ecf229 100644 --- a/compiler/rustc_mir/src/transform/coverage/spans.rs +++ b/compiler/rustc_mir/src/transform/coverage/spans.rs @@ -1,9 +1,8 @@ use super::debug::term_type; -use super::graph::{BasicCoverageBlock, BasicCoverageBlocks}; +use super::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph}; use crate::util::spanview::source_range_no_file; -use rustc_data_structures::graph::dominators::Dominators; use rustc_data_structures::graph::WithNumNodes; use rustc_index::bit_set::BitSet; use rustc_middle::mir::{ @@ -69,7 +68,7 @@ impl CoverageStatement { #[derive(Debug, Clone)] pub(crate) struct CoverageSpan { pub span: Span, - pub bcb_leader_bb: BasicBlock, + pub bcb: BasicCoverageBlock, pub coverage_statements: Vec, pub is_closure: bool, } @@ -78,7 +77,7 @@ impl CoverageSpan { pub fn for_statement( statement: &Statement<'tcx>, span: Span, - bcb: &BasicCoverageBlock, + bcb: BasicCoverageBlock, bb: BasicBlock, stmt_index: usize, ) -> Self { @@ -92,16 +91,16 @@ impl CoverageSpan { Self { span, - bcb_leader_bb: bcb.leader_bb(), + bcb, coverage_statements: vec![CoverageStatement::Statement(bb, span, stmt_index)], is_closure, } } - pub fn for_terminator(span: Span, bcb: &BasicCoverageBlock, bb: BasicBlock) -> Self { + pub fn for_terminator(span: Span, bcb: BasicCoverageBlock, bb: BasicBlock) -> Self { Self { span, - bcb_leader_bb: bcb.leader_bb(), + bcb, coverage_statements: vec![CoverageStatement::Terminator(bb, span)], is_closure: false, } @@ -132,7 +131,7 @@ impl CoverageSpan { #[inline] pub fn is_in_same_bcb(&self, other: &Self) -> bool { - self.bcb_leader_bb == other.bcb_leader_bb + self.bcb == other.bcb } pub fn format_coverage_statements( @@ -164,15 +163,12 @@ pub struct CoverageSpans<'a, 'tcx> { /// The MIR, used to look up `BasicBlockData`. mir_body: &'a mir::Body<'tcx>, - /// A snapshot of the MIR CFG dominators before injecting any coverage statements. - dominators: Dominators, - /// A `Span` covering the function body of the MIR (typically from left curly brace to right /// curly brace). body_span: Span, /// The BasicCoverageBlock Control Flow Graph (BCB CFG). - basic_coverage_blocks: &'a BasicCoverageBlocks, + basic_coverage_blocks: &'a CoverageGraph, /// The initial set of `CoverageSpan`s, sorted by `Span` (`lo` and `hi`) and by relative /// dominance between the `BasicCoverageBlock`s of equal `Span`s. @@ -213,12 +209,10 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> { pub(crate) fn generate_coverage_spans( mir_body: &'a mir::Body<'tcx>, body_span: Span, - basic_coverage_blocks: &'a BasicCoverageBlocks, + basic_coverage_blocks: &'a CoverageGraph, ) -> Vec { - let dominators = mir_body.dominators(); let mut coverage_spans = CoverageSpans { mir_body, - dominators, body_span, basic_coverage_blocks, sorted_spans_iter: None, @@ -246,7 +240,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> { /// The basic steps are: /// /// 1. Extract an initial set of spans from the `Statement`s and `Terminator`s of each - /// `BasicCoverageBlock`. + /// `BasicCoverageBlockData`. /// 2. Sort the spans by span.lo() (starting position). Spans that start at the same position /// are sorted with longer spans before shorter spans; and equal spans are sorted /// (deterministically) based on "dominator" relationship (if any). @@ -263,8 +257,8 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> { /// to be). fn mir_to_initial_sorted_coverage_spans(&self) -> Vec { let mut initial_spans = Vec::::with_capacity(self.mir_body.num_nodes() * 2); - for bcb in self.basic_coverage_blocks.iter() { - for coverage_span in self.bcb_to_initial_coverage_spans(bcb) { + for (bcb, bcb_data) in self.basic_coverage_blocks.iter_enumerated() { + for coverage_span in self.bcb_to_initial_coverage_spans(bcb, bcb_data) { initial_spans.push(coverage_span); } } @@ -285,7 +279,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> { // dominators always come after the dominated equal spans). When later // comparing two spans in order, the first will either dominate the second, // or they will have no dominator relationship. - self.dominators.rank_partial_cmp(b.bcb_leader_bb, a.bcb_leader_bb) + self.basic_coverage_blocks.dominators().rank_partial_cmp(b.bcb, a.bcb) } } else { // Sort hi() in reverse order so shorter spans are attempted after longer spans. @@ -357,13 +351,13 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> { let mut has_coverage = BitSet::new_empty(basic_coverage_blocks.num_nodes()); for covspan in &refined_spans { if !covspan.span.is_empty() { - has_coverage.insert(covspan.bcb_leader_bb); + has_coverage.insert(covspan.bcb); } } refined_spans.retain(|covspan| { !(covspan.span.is_empty() - && is_goto(&mir_body[covspan.bcb_leader_bb].terminator().kind) - && has_coverage.contains(covspan.bcb_leader_bb)) + && is_goto(&basic_coverage_blocks[covspan.bcb].terminator(mir_body).kind) + && has_coverage.contains(covspan.bcb)) }); // Remove `CoverageSpan`s derived from closures, originally added to ensure the coverage @@ -374,12 +368,17 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> { } // Generate a set of `CoverageSpan`s from the filtered set of `Statement`s and `Terminator`s of - // the `BasicBlock`(s) in the given `BasicCoverageBlock`. One `CoverageSpan` is generated + // the `BasicBlock`(s) in the given `BasicCoverageBlockData`. One `CoverageSpan` is generated // for each `Statement` and `Terminator`. (Note that subsequent stages of coverage analysis will // merge some `CoverageSpan`s, at which point a `CoverageSpan` may represent multiple // `Statement`s and/or `Terminator`s.) - fn bcb_to_initial_coverage_spans(&self, bcb: &BasicCoverageBlock) -> Vec { - bcb.blocks + fn bcb_to_initial_coverage_spans( + &self, + bcb: BasicCoverageBlock, + bcb_data: &'a BasicCoverageBlockData, + ) -> Vec { + bcb_data + .basic_blocks .iter() .map(|bbref| { let bb = *bbref; @@ -636,7 +635,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> { } fn span_bcb_is_dominated_by(&self, covspan: &CoverageSpan, dom_covspan: &CoverageSpan) -> bool { - self.dominators.is_dominated_by(covspan.bcb_leader_bb, dom_covspan.bcb_leader_bb) + self.basic_coverage_blocks.is_dominated_by(covspan.bcb, dom_covspan.bcb) } } diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.lazy_boolean.json b/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.lazy_boolean.json index 95a1dcd3b8e..5a953b90b42 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.lazy_boolean.json +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.lazy_boolean.json @@ -17,14 +17,14 @@ }, "lines": { "count": 40, - "covered": 32, - "percent": 80 + "covered": 30, + "percent": 75 }, "regions": { - "count": 39, - "covered": 28, + "count": 37, + "covered": 26, "notcovered": 11, - "percent": 71.7948717948718 + "percent": 70.27027027027027 } } } @@ -42,14 +42,14 @@ }, "lines": { "count": 40, - "covered": 32, - "percent": 80 + "covered": 30, + "percent": 75 }, "regions": { - "count": 39, - "covered": 28, + "count": 37, + "covered": 26, "notcovered": 11, - "percent": 71.7948717948718 + "percent": 70.27027027027027 } } } diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.loops_and_branches.json b/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.loops_and_branches.json index aec85cd0329..cb74a1b7e27 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.loops_and_branches.json +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.loops_and_branches.json @@ -21,10 +21,10 @@ "percent": 100 }, "regions": { - "count": 10, + "count": 9, "covered": 8, - "notcovered": 2, - "percent": 80 + "notcovered": 1, + "percent": 88.88888888888889 } } } @@ -46,10 +46,10 @@ "percent": 100 }, "regions": { - "count": 10, + "count": 9, "covered": 8, - "notcovered": 2, - "percent": 80 + "notcovered": 1, + "percent": 88.88888888888889 } } } diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.nested_loops.json b/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.nested_loops.json index dbe4f9ca6fd..68163eb7636 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.nested_loops.json +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.nested_loops.json @@ -17,14 +17,14 @@ }, "lines": { "count": 21, - "covered": 17, - "percent": 80.95238095238095 + "covered": 16, + "percent": 76.19047619047619 }, "regions": { - "count": 20, - "covered": 16, + "count": 18, + "covered": 14, "notcovered": 4, - "percent": 80 + "percent": 77.77777777777779 } } } @@ -42,14 +42,14 @@ }, "lines": { "count": 21, - "covered": 17, - "percent": 80.95238095238095 + "covered": 16, + "percent": 76.19047619047619 }, "regions": { - "count": 20, - "covered": 16, + "count": 18, + "covered": 14, "notcovered": 4, - "percent": 80 + "percent": 77.77777777777779 } } } diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.try_error_result.json b/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.try_error_result.json index e845ee29fa4..39e17359eee 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.try_error_result.json +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.try_error_result.json @@ -16,15 +16,15 @@ "percent": 100 }, "lines": { - "count": 20, - "covered": 19, - "percent": 95 + "count": 19, + "covered": 18, + "percent": 94.73684210526315 }, "regions": { - "count": 20, - "covered": 17, + "count": 18, + "covered": 15, "notcovered": 3, - "percent": 85 + "percent": 83.33333333333334 } } } @@ -41,15 +41,15 @@ "percent": 100 }, "lines": { - "count": 20, - "covered": 19, - "percent": 95 + "count": 19, + "covered": 18, + "percent": 94.73684210526315 }, "regions": { - "count": 20, - "covered": 17, + "count": 18, + "covered": 15, "notcovered": 3, - "percent": 85 + "percent": 83.33333333333334 } } } diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.while.json b/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.while.json index 27862087ed5..339c6555668 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.while.json +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.while.json @@ -21,10 +21,10 @@ "percent": 75 }, "regions": { - "count": 5, + "count": 4, "covered": 3, - "notcovered": 2, - "percent": 60 + "notcovered": 1, + "percent": 75 } } } @@ -46,10 +46,10 @@ "percent": 75 }, "regions": { - "count": 5, + "count": 4, "covered": 3, - "notcovered": 2, - "percent": 60 + "notcovered": 1, + "percent": 75 } } } diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.while_early_return.json b/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.while_early_return.json index 555ac745d53..a116a91a60a 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.while_early_return.json +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.while_early_return.json @@ -16,15 +16,15 @@ "percent": 100 }, "lines": { - "count": 18, + "count": 17, "covered": 15, - "percent": 83.33333333333334 + "percent": 88.23529411764706 }, "regions": { - "count": 11, + "count": 10, "covered": 8, - "notcovered": 3, - "percent": 72.72727272727273 + "notcovered": 2, + "percent": 80 } } } @@ -41,15 +41,15 @@ "percent": 100 }, "lines": { - "count": 18, + "count": 17, "covered": 15, - "percent": 83.33333333333334 + "percent": 88.23529411764706 }, "regions": { - "count": 11, + "count": 10, "covered": 8, - "notcovered": 3, - "percent": 72.72727272727273 + "notcovered": 2, + "percent": 80 } } } diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.lazy_boolean.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.lazy_boolean.txt index f01f69f2496..1b503033911 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.lazy_boolean.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.lazy_boolean.txt @@ -50,7 +50,7 @@ 47| 0| { 48| 0| c = 400 49| 0| ; - 50| 1| } + 50| 0| } 51| | 52| 1| if !is_true { 53| 0| a = 2; @@ -60,6 +60,6 @@ 57| 1| b = 30; 58| 1| } else { 59| 0| c = 400; - 60| 1| } + 60| 0| } 61| 1|} diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.nested_loops.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.nested_loops.txt index e0545c76f78..c9f373bf6a7 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.nested_loops.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.nested_loops.txt @@ -19,8 +19,8 @@ 19| 0| a -= 2; 20| 0| } 21| 2| } - 22| 3| } + 22| 2| } 23| 0| countdown -= 1; - 24| 1| } + 24| 0| } 25| 1|} diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.try_error_result.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.try_error_result.txt index 05d72d0de46..c43b492db60 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.try_error_result.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.try_error_result.txt @@ -6,7 +6,7 @@ 6| 1| Err(()) 7| | } else { 8| 5| Ok(()) - 9| 1| } + 9| | } 10| 6|} 11| | 12| |fn main() -> Result<(),()> { @@ -31,7 +31,7 @@ 31| 5| call(/*return_error=*/ false)?; ^0 32| 5| } - 33| 6| } + 33| 5| } 34| 0| Ok(()) 35| 2|} diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.while_early_return.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.while_early_return.txt index 2e0c4022bed..e5c5b05a6fc 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.while_early_return.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.while_early_return.txt @@ -24,7 +24,7 @@ 24| | else 25| | { 26| 1| Err(1) - 27| 0| } + 27| | } 28| | ; 29| | } 30| 6| countdown diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.drop_trait.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.drop_trait.txt index 447c3c89562..2bafe7d88e2 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.drop_trait.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.drop_trait.txt @@ -4,14 +4,13 @@ Counter in file 0 15:9 -> 17:42, #1 Counter in file 0 19:8 -> 19:12, (#1 + 0) Counter in file 0 20:9 -> 21:22, #2 Counter in file 0 27:1 -> 27:2, #4 -Counter in file 0 27:1 -> 27:2, (#2 + 0) Emitting segments for file: ../coverage/drop_trait.rs Combined regions: 9:24 -> 11:6 (count=2) 15:9 -> 17:42 (count=1) 19:8 -> 19:12 (count=1) 20:9 -> 21:22 (count=1) - 27:1 -> 27:2 (count=2) + 27:1 -> 27:2 (count=1) Segment at 9:24 (count = 2), RegionEntry Segment at 11:6 (count = 0), Skipped Segment at 15:9 (count = 1), RegionEntry @@ -20,5 +19,5 @@ Segment at 19:8 (count = 1), RegionEntry Segment at 19:12 (count = 0), Skipped Segment at 20:9 (count = 1), RegionEntry Segment at 21:22 (count = 0), Skipped -Segment at 27:1 (count = 2), RegionEntry +Segment at 27:1 (count = 1), RegionEntry Segment at 27:2 (count = 0), Skipped diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.generics.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.generics.txt index 5843b917588..a13b1f3d786 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.generics.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.generics.txt @@ -5,7 +5,6 @@ Counter in file 0 23:9 -> 28:28, #1 Counter in file 0 30:8 -> 30:12, (#1 + 0) Counter in file 0 31:9 -> 32:22, #2 Counter in file 0 38:1 -> 38:2, #4 -Counter in file 0 38:1 -> 38:2, (#2 + 0) Counter in file 0 10:49 -> 12:6, #1 Counter in file 0 10:49 -> 12:6, #1 Emitting segments for file: ../coverage/generics.rs @@ -15,7 +14,7 @@ Combined regions: 23:9 -> 28:28 (count=1) 30:8 -> 30:12 (count=1) 31:9 -> 32:22 (count=1) - 38:1 -> 38:2 (count=2) + 38:1 -> 38:2 (count=1) Segment at 10:49 (count = 3), RegionEntry Segment at 12:6 (count = 0), Skipped Segment at 17:24 (count = 2), RegionEntry @@ -26,7 +25,7 @@ Segment at 30:8 (count = 1), RegionEntry Segment at 30:12 (count = 0), Skipped Segment at 31:9 (count = 1), RegionEntry Segment at 32:22 (count = 0), Skipped -Segment at 38:1 (count = 2), RegionEntry +Segment at 38:1 (count = 1), RegionEntry Segment at 38:2 (count = 0), Skipped Emitting segments for function: _RNvMCs4fqI2P2rA04_8genericsINtB2_8FireworkdE12set_strengthB2_ Combined regions: diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.if_else.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.if_else.txt index 660e85f91f5..270a6f2b14a 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.if_else.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.if_else.txt @@ -2,22 +2,18 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/ Counter in file 0 7:9 -> 11:16, #1 Counter in file 0 12:5 -> 17:6, #2 Counter in file 0 20:9 -> 22:16, #3 -Counter in file 0 23:6 -> 23:7, (#2 + 0) Counter in file 0 26:9 -> 26:16, #4 Counter in file 0 27:5 -> 32:6, #5 Counter in file 0 34:5 -> 39:6, #6 -Counter in file 0 39:6 -> 39:7, (#5 + 0) Counter in file 0 40:1 -> 40:2, #7 Emitting segments for file: ../coverage/if_else.rs Combined regions: 7:9 -> 11:16 (count=1) 12:5 -> 17:6 (count=1) 20:9 -> 22:16 (count=0) - 23:6 -> 23:7 (count=1) 26:9 -> 26:16 (count=1) 27:5 -> 32:6 (count=1) 34:5 -> 39:6 (count=0) - 39:6 -> 39:7 (count=1) 40:1 -> 40:2 (count=1) Segment at 7:9 (count = 1), RegionEntry Segment at 11:16 (count = 0), Skipped @@ -25,14 +21,11 @@ Segment at 12:5 (count = 1), RegionEntry Segment at 17:6 (count = 0), Skipped Segment at 20:9 (count = 0), RegionEntry Segment at 22:16 (count = 0), Skipped -Segment at 23:6 (count = 1), RegionEntry -Segment at 23:7 (count = 0), Skipped Segment at 26:9 (count = 1), RegionEntry Segment at 26:16 (count = 0), Skipped Segment at 27:5 (count = 1), RegionEntry Segment at 32:6 (count = 0), Skipped Segment at 34:5 (count = 0), RegionEntry -Segment at 39:6 (count = 1), RegionEntry -Segment at 39:7 (count = 0), Skipped +Segment at 39:6 (count = 0), Skipped Segment at 40:1 (count = 1), RegionEntry Segment at 40:2 (count = 0), Skipped diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.lazy_boolean.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.lazy_boolean.txt index dd93c3a9392..4561fcc5b36 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.lazy_boolean.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.lazy_boolean.txt @@ -29,14 +29,12 @@ Counter in file 0 38:6 -> 38:7, #22 Counter in file 0 41:9 -> 41:16, #23 Counter in file 0 42:5 -> 45:6, #24 Counter in file 0 47:5 -> 50:6, #25 -Counter in file 0 50:6 -> 50:7, (#24 + 0) Counter in file 0 52:8 -> 52:16, #26 Counter in file 0 52:17 -> 54:6, #27 Counter in file 0 54:6 -> 54:7, #28 Counter in file 0 56:8 -> 56:15, #29 Counter in file 0 56:16 -> 58:6, #30 Counter in file 0 58:12 -> 60:6, #31 -Counter in file 0 60:6 -> 60:7, (#30 + 0) Counter in file 0 61:1 -> 61:2, #32 Emitting segments for file: ../coverage/lazy_boolean.rs Combined regions: @@ -66,14 +64,12 @@ Combined regions: 41:9 -> 41:16 (count=1) 42:5 -> 45:6 (count=1) 47:5 -> 50:6 (count=0) - 50:6 -> 50:7 (count=1) 52:8 -> 52:16 (count=1) 52:17 -> 54:6 (count=0) 54:6 -> 54:7 (count=1) 56:8 -> 56:15 (count=1) 56:16 -> 58:6 (count=1) 58:12 -> 60:6 (count=0) - 60:6 -> 60:7 (count=1) 61:1 -> 61:2 (count=1) Segment at 7:9 (count = 1), RegionEntry Segment at 9:42 (count = 0), Skipped @@ -120,8 +116,7 @@ Segment at 41:16 (count = 0), Skipped Segment at 42:5 (count = 1), RegionEntry Segment at 45:6 (count = 0), Skipped Segment at 47:5 (count = 0), RegionEntry -Segment at 50:6 (count = 1), RegionEntry -Segment at 50:7 (count = 0), Skipped +Segment at 50:6 (count = 0), Skipped Segment at 52:8 (count = 1), RegionEntry Segment at 52:16 (count = 0), Skipped Segment at 52:17 (count = 0), RegionEntry @@ -132,7 +127,6 @@ Segment at 56:15 (count = 0), Skipped Segment at 56:16 (count = 1), RegionEntry Segment at 58:6 (count = 0), Skipped Segment at 58:12 (count = 0), RegionEntry -Segment at 60:6 (count = 1), RegionEntry -Segment at 60:7 (count = 0), Skipped +Segment at 60:6 (count = 0), Skipped Segment at 61:1 (count = 1), RegionEntry Segment at 61:2 (count = 0), Skipped diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.loops_and_branches.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.loops_and_branches.txt index d6e4403268a..7cde2205cbf 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.loops_and_branches.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.loops_and_branches.txt @@ -7,7 +7,6 @@ Counter in file 0 15:31 -> 15:32, #8 Counter in file 0 17:10 -> 17:11, #10 Counter in file 0 18:9 -> 18:15, #11 Counter in file 0 19:5 -> 19:6, #12 -Counter in file 0 19:5 -> 19:6, (#8 + 0) Counter in file 0 22:11 -> 25:2, #1 Emitting segments for file: ../coverage/loops_and_branches.rs Combined regions: diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.nested_loops.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.nested_loops.txt index eec4aec79e6..59fb5c366f2 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.nested_loops.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.nested_loops.txt @@ -14,10 +14,8 @@ Counter in file 0 17:21 -> 17:33, #10 Counter in file 0 19:21 -> 21:14, #11 Counter in file 0 21:14 -> 21:15, #12 Counter in file 0 22:10 -> 22:11, #13 -Counter in file 0 22:10 -> 22:11, (#3 + 0) Counter in file 0 23:9 -> 23:23, #14 Counter in file 0 24:6 -> 24:7, #15 -Counter in file 0 24:6 -> 24:7, (#1 + 0) Counter in file 0 25:1 -> 25:2, #16 Emitting segments for file: ../coverage/nested_loops.rs Combined regions: @@ -35,9 +33,9 @@ Combined regions: 17:21 -> 17:33 (count=1) 19:21 -> 21:14 (count=0) 21:14 -> 21:15 (count=2) - 22:10 -> 22:11 (count=3) + 22:10 -> 22:11 (count=2) 23:9 -> 23:23 (count=0) - 24:6 -> 24:7 (count=1) + 24:6 -> 24:7 (count=0) 25:1 -> 25:2 (count=1) Segment at 2:9 (count = 1), RegionEntry Segment at 3:27 (count = 0), Skipped @@ -66,11 +64,11 @@ Segment at 17:33 (count = 0), Skipped Segment at 19:21 (count = 0), RegionEntry Segment at 21:14 (count = 2), RegionEntry Segment at 21:15 (count = 0), Skipped -Segment at 22:10 (count = 3), RegionEntry +Segment at 22:10 (count = 2), RegionEntry Segment at 22:11 (count = 0), Skipped Segment at 23:9 (count = 0), RegionEntry Segment at 23:23 (count = 0), Skipped -Segment at 24:6 (count = 1), RegionEntry +Segment at 24:6 (count = 0), RegionEntry Segment at 24:7 (count = 0), Skipped Segment at 25:1 (count = 1), RegionEntry Segment at 25:2 (count = 0), Skipped diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.try_error_result.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.try_error_result.txt index d510223417a..7dea637551d 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.try_error_result.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.try_error_result.txt @@ -10,21 +10,18 @@ Counter in file 0 31:42 -> 31:43, #8 Counter in file 0 32:10 -> 32:11, #9 Counter in file 0 32:10 -> 32:11, #10 Counter in file 0 33:6 -> 33:7, #11 -Counter in file 0 33:6 -> 33:7, (#1 + 0) Counter in file 0 34:5 -> 34:11, #12 Counter in file 0 35:1 -> 35:2, #13 Counter in file 0 35:1 -> 35:2, #14 Counter in file 0 5:8 -> 5:20, #1 Counter in file 0 6:9 -> 6:16, #2 Counter in file 0 8:9 -> 8:15, #3 -Counter in file 0 9:6 -> 9:7, (#2 + 0) Counter in file 0 10:1 -> 10:2, #4 Emitting segments for file: ../coverage/try_error_result.rs Combined regions: 5:8 -> 5:20 (count=6) 6:9 -> 6:16 (count=1) 8:9 -> 8:15 (count=5) - 9:6 -> 9:7 (count=1) 10:1 -> 10:2 (count=6) 13:9 -> 14:23 (count=1) 17:9 -> 17:10 (count=6) @@ -35,7 +32,7 @@ Combined regions: 31:13 -> 31:42 (count=5) 31:42 -> 31:43 (count=0) 32:10 -> 32:11 (count=5) - 33:6 -> 33:7 (count=6) + 33:6 -> 33:7 (count=5) 34:5 -> 34:11 (count=0) 35:1 -> 35:2 (count=2) Segment at 5:8 (count = 6), RegionEntry @@ -44,8 +41,6 @@ Segment at 6:9 (count = 1), RegionEntry Segment at 6:16 (count = 0), Skipped Segment at 8:9 (count = 5), RegionEntry Segment at 8:15 (count = 0), Skipped -Segment at 9:6 (count = 1), RegionEntry -Segment at 9:7 (count = 0), Skipped Segment at 10:1 (count = 6), RegionEntry Segment at 10:2 (count = 0), Skipped Segment at 13:9 (count = 1), RegionEntry @@ -64,7 +59,7 @@ Segment at 31:42 (count = 0), RegionEntry Segment at 31:43 (count = 0), Skipped Segment at 32:10 (count = 5), RegionEntry Segment at 32:11 (count = 0), Skipped -Segment at 33:6 (count = 6), RegionEntry +Segment at 33:6 (count = 5), RegionEntry Segment at 33:7 (count = 0), Skipped Segment at 34:5 (count = 0), RegionEntry Segment at 34:11 (count = 0), Skipped diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.while.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.while.txt index 52c809b5325..a2be958660e 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.while.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.while.txt @@ -2,21 +2,18 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/ Counter in file 0 2:9 -> 2:16, #1 Counter in file 0 3:11 -> 3:20, #2 Counter in file 0 3:21 -> 4:6, #3 -Counter in file 0 4:6 -> 4:7, (#3 + 0) Counter in file 0 5:1 -> 5:2, #4 Emitting segments for file: ../coverage/while.rs Combined regions: 2:9 -> 2:16 (count=1) 3:11 -> 3:20 (count=1) 3:21 -> 4:6 (count=0) - 4:6 -> 4:7 (count=0) 5:1 -> 5:2 (count=1) Segment at 2:9 (count = 1), RegionEntry Segment at 2:16 (count = 0), Skipped Segment at 3:11 (count = 1), RegionEntry Segment at 3:20 (count = 0), Skipped Segment at 3:21 (count = 0), RegionEntry -Segment at 4:6 (count = 0), RegionEntry -Segment at 4:7 (count = 0), Skipped +Segment at 4:6 (count = 0), Skipped Segment at 5:1 (count = 1), RegionEntry Segment at 5:2 (count = 0), Skipped diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.while_early_return.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.while_early_return.txt index 30d14f4f987..02ab24050ba 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.while_early_return.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.while_early_return.txt @@ -5,7 +5,6 @@ Counter in file 0 12:13 -> 14:14, #3 Counter in file 0 18:21 -> 20:22, #4 Counter in file 0 22:21 -> 22:27, #5 Counter in file 0 26:21 -> 26:27, #6 -Counter in file 0 27:18 -> 27:19, (#5 + 0) Counter in file 0 30:9 -> 32:10, #7 Counter in file 0 35:5 -> 35:11, #8 Counter in file 0 36:1 -> 36:2, #9 @@ -18,7 +17,6 @@ Combined regions: 18:21 -> 20:22 (count=1) 22:21 -> 22:27 (count=0) 26:21 -> 26:27 (count=1) - 27:18 -> 27:19 (count=0) 30:9 -> 32:10 (count=6) 35:5 -> 35:11 (count=0) 36:1 -> 36:2 (count=2) @@ -34,8 +32,6 @@ Segment at 22:21 (count = 0), RegionEntry Segment at 22:27 (count = 0), Skipped Segment at 26:21 (count = 1), RegionEntry Segment at 26:27 (count = 0), Skipped -Segment at 27:18 (count = 0), RegionEntry -Segment at 27:19 (count = 0), Skipped Segment at 30:9 (count = 6), RegionEntry Segment at 32:10 (count = 0), Skipped Segment at 35:5 (count = 0), RegionEntry diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.lazy_boolean.json b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.lazy_boolean.json index 95a1dcd3b8e..5a953b90b42 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.lazy_boolean.json +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.lazy_boolean.json @@ -17,14 +17,14 @@ }, "lines": { "count": 40, - "covered": 32, - "percent": 80 + "covered": 30, + "percent": 75 }, "regions": { - "count": 39, - "covered": 28, + "count": 37, + "covered": 26, "notcovered": 11, - "percent": 71.7948717948718 + "percent": 70.27027027027027 } } } @@ -42,14 +42,14 @@ }, "lines": { "count": 40, - "covered": 32, - "percent": 80 + "covered": 30, + "percent": 75 }, "regions": { - "count": 39, - "covered": 28, + "count": 37, + "covered": 26, "notcovered": 11, - "percent": 71.7948717948718 + "percent": 70.27027027027027 } } } diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.loops_and_branches.json b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.loops_and_branches.json index aec85cd0329..cb74a1b7e27 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.loops_and_branches.json +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.loops_and_branches.json @@ -21,10 +21,10 @@ "percent": 100 }, "regions": { - "count": 10, + "count": 9, "covered": 8, - "notcovered": 2, - "percent": 80 + "notcovered": 1, + "percent": 88.88888888888889 } } } @@ -46,10 +46,10 @@ "percent": 100 }, "regions": { - "count": 10, + "count": 9, "covered": 8, - "notcovered": 2, - "percent": 80 + "notcovered": 1, + "percent": 88.88888888888889 } } } diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.nested_loops.json b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.nested_loops.json index dbe4f9ca6fd..68163eb7636 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.nested_loops.json +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.nested_loops.json @@ -17,14 +17,14 @@ }, "lines": { "count": 21, - "covered": 17, - "percent": 80.95238095238095 + "covered": 16, + "percent": 76.19047619047619 }, "regions": { - "count": 20, - "covered": 16, + "count": 18, + "covered": 14, "notcovered": 4, - "percent": 80 + "percent": 77.77777777777779 } } } @@ -42,14 +42,14 @@ }, "lines": { "count": 21, - "covered": 17, - "percent": 80.95238095238095 + "covered": 16, + "percent": 76.19047619047619 }, "regions": { - "count": 20, - "covered": 16, + "count": 18, + "covered": 14, "notcovered": 4, - "percent": 80 + "percent": 77.77777777777779 } } } diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.try_error_result.json b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.try_error_result.json index e845ee29fa4..39e17359eee 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.try_error_result.json +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.try_error_result.json @@ -16,15 +16,15 @@ "percent": 100 }, "lines": { - "count": 20, - "covered": 19, - "percent": 95 + "count": 19, + "covered": 18, + "percent": 94.73684210526315 }, "regions": { - "count": 20, - "covered": 17, + "count": 18, + "covered": 15, "notcovered": 3, - "percent": 85 + "percent": 83.33333333333334 } } } @@ -41,15 +41,15 @@ "percent": 100 }, "lines": { - "count": 20, - "covered": 19, - "percent": 95 + "count": 19, + "covered": 18, + "percent": 94.73684210526315 }, "regions": { - "count": 20, - "covered": 17, + "count": 18, + "covered": 15, "notcovered": 3, - "percent": 85 + "percent": 83.33333333333334 } } } diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.while.json b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.while.json index 27862087ed5..339c6555668 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.while.json +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.while.json @@ -21,10 +21,10 @@ "percent": 75 }, "regions": { - "count": 5, + "count": 4, "covered": 3, - "notcovered": 2, - "percent": 60 + "notcovered": 1, + "percent": 75 } } } @@ -46,10 +46,10 @@ "percent": 75 }, "regions": { - "count": 5, + "count": 4, "covered": 3, - "notcovered": 2, - "percent": 60 + "notcovered": 1, + "percent": 75 } } } diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.while_early_return.json b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.while_early_return.json index 555ac745d53..a116a91a60a 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.while_early_return.json +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.while_early_return.json @@ -16,15 +16,15 @@ "percent": 100 }, "lines": { - "count": 18, + "count": 17, "covered": 15, - "percent": 83.33333333333334 + "percent": 88.23529411764706 }, "regions": { - "count": 11, + "count": 10, "covered": 8, - "notcovered": 3, - "percent": 72.72727272727273 + "notcovered": 2, + "percent": 80 } } } @@ -41,15 +41,15 @@ "percent": 100 }, "lines": { - "count": 18, + "count": 17, "covered": 15, - "percent": 83.33333333333334 + "percent": 88.23529411764706 }, "regions": { - "count": 11, + "count": 10, "covered": 8, - "notcovered": 3, - "percent": 72.72727272727273 + "notcovered": 2, + "percent": 80 } } } diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.lazy_boolean.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.lazy_boolean.txt index f01f69f2496..1b503033911 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.lazy_boolean.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.lazy_boolean.txt @@ -50,7 +50,7 @@ 47| 0| { 48| 0| c = 400 49| 0| ; - 50| 1| } + 50| 0| } 51| | 52| 1| if !is_true { 53| 0| a = 2; @@ -60,6 +60,6 @@ 57| 1| b = 30; 58| 1| } else { 59| 0| c = 400; - 60| 1| } + 60| 0| } 61| 1|} diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.nested_loops.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.nested_loops.txt index e0545c76f78..c9f373bf6a7 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.nested_loops.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.nested_loops.txt @@ -19,8 +19,8 @@ 19| 0| a -= 2; 20| 0| } 21| 2| } - 22| 3| } + 22| 2| } 23| 0| countdown -= 1; - 24| 1| } + 24| 0| } 25| 1|} diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.try_error_result.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.try_error_result.txt index 05d72d0de46..c43b492db60 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.try_error_result.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.try_error_result.txt @@ -6,7 +6,7 @@ 6| 1| Err(()) 7| | } else { 8| 5| Ok(()) - 9| 1| } + 9| | } 10| 6|} 11| | 12| |fn main() -> Result<(),()> { @@ -31,7 +31,7 @@ 31| 5| call(/*return_error=*/ false)?; ^0 32| 5| } - 33| 6| } + 33| 5| } 34| 0| Ok(()) 35| 2|} diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.while_early_return.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.while_early_return.txt index 2e0c4022bed..e5c5b05a6fc 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.while_early_return.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.while_early_return.txt @@ -24,7 +24,7 @@ 24| | else 25| | { 26| 1| Err(1) - 27| 0| } + 27| | } 28| | ; 29| | } 30| 6| countdown diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.drop_trait.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.drop_trait.txt index e416a84820a..124a01af342 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.drop_trait.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.drop_trait.txt @@ -4,14 +4,13 @@ Counter in file 0 15:9 -> 17:42, #1 Counter in file 0 19:8 -> 19:12, (#1 + 0) Counter in file 0 20:9 -> 21:22, #2 Counter in file 0 27:1 -> 27:2, #4 -Counter in file 0 27:1 -> 27:2, (#2 + 0) Emitting segments for file: ../coverage/drop_trait.rs Combined regions: 9:24 -> 11:6 (count=2) 15:9 -> 17:42 (count=1) 19:8 -> 19:12 (count=1) 20:9 -> 21:22 (count=1) - 27:1 -> 27:2 (count=2) + 27:1 -> 27:2 (count=1) Segment at 9:24 (count = 2), RegionEntry Segment at 11:6 (count = 0), Skipped Segment at 15:9 (count = 1), RegionEntry @@ -20,5 +19,5 @@ Segment at 19:8 (count = 1), RegionEntry Segment at 19:12 (count = 0), Skipped Segment at 20:9 (count = 1), RegionEntry Segment at 21:22 (count = 0), Skipped -Segment at 27:1 (count = 2), RegionEntry +Segment at 27:1 (count = 1), RegionEntry Segment at 27:2 (count = 0), Skipped diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.generics.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.generics.txt index 9e33b48fc29..a0e9146035e 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.generics.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.generics.txt @@ -5,7 +5,6 @@ Counter in file 0 23:9 -> 28:28, #1 Counter in file 0 30:8 -> 30:12, (#1 + 0) Counter in file 0 31:9 -> 32:22, #2 Counter in file 0 38:1 -> 38:2, #4 -Counter in file 0 38:1 -> 38:2, (#2 + 0) Counter in file 0 10:49 -> 12:6, #1 Counter in file 0 10:49 -> 12:6, #1 Emitting segments for file: ../coverage/generics.rs @@ -15,7 +14,7 @@ Combined regions: 23:9 -> 28:28 (count=1) 30:8 -> 30:12 (count=1) 31:9 -> 32:22 (count=1) - 38:1 -> 38:2 (count=2) + 38:1 -> 38:2 (count=1) Segment at 10:49 (count = 3), RegionEntry Segment at 12:6 (count = 0), Skipped Segment at 17:24 (count = 2), RegionEntry @@ -26,7 +25,7 @@ Segment at 30:8 (count = 1), RegionEntry Segment at 30:12 (count = 0), Skipped Segment at 31:9 (count = 1), RegionEntry Segment at 32:22 (count = 0), Skipped -Segment at 38:1 (count = 2), RegionEntry +Segment at 38:1 (count = 1), RegionEntry Segment at 38:2 (count = 0), Skipped Emitting segments for function: _RNvMCs4fqI2P2rA04_8genericsINtB2_8FireworkdE12set_strengthB2_ Combined regions: diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.if_else.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.if_else.txt index a620bf8ae4a..9406b6a269d 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.if_else.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.if_else.txt @@ -2,22 +2,18 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/ Counter in file 0 7:9 -> 11:16, #1 Counter in file 0 12:5 -> 17:6, #2 Counter in file 0 20:9 -> 22:16, #3 -Counter in file 0 23:6 -> 23:7, (#2 + 0) Counter in file 0 26:9 -> 26:16, #4 Counter in file 0 27:5 -> 32:6, #5 Counter in file 0 34:5 -> 39:6, #6 -Counter in file 0 39:6 -> 39:7, (#5 + 0) Counter in file 0 40:1 -> 40:2, #7 Emitting segments for file: ../coverage/if_else.rs Combined regions: 7:9 -> 11:16 (count=1) 12:5 -> 17:6 (count=1) 20:9 -> 22:16 (count=0) - 23:6 -> 23:7 (count=1) 26:9 -> 26:16 (count=1) 27:5 -> 32:6 (count=1) 34:5 -> 39:6 (count=0) - 39:6 -> 39:7 (count=1) 40:1 -> 40:2 (count=1) Segment at 7:9 (count = 1), RegionEntry Segment at 11:16 (count = 0), Skipped @@ -25,14 +21,11 @@ Segment at 12:5 (count = 1), RegionEntry Segment at 17:6 (count = 0), Skipped Segment at 20:9 (count = 0), RegionEntry Segment at 22:16 (count = 0), Skipped -Segment at 23:6 (count = 1), RegionEntry -Segment at 23:7 (count = 0), Skipped Segment at 26:9 (count = 1), RegionEntry Segment at 26:16 (count = 0), Skipped Segment at 27:5 (count = 1), RegionEntry Segment at 32:6 (count = 0), Skipped Segment at 34:5 (count = 0), RegionEntry -Segment at 39:6 (count = 1), RegionEntry -Segment at 39:7 (count = 0), Skipped +Segment at 39:6 (count = 0), Skipped Segment at 40:1 (count = 1), RegionEntry Segment at 40:2 (count = 0), Skipped diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.lazy_boolean.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.lazy_boolean.txt index 0f54f4904b0..c95275c6223 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.lazy_boolean.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.lazy_boolean.txt @@ -29,14 +29,12 @@ Counter in file 0 38:6 -> 38:7, #22 Counter in file 0 41:9 -> 41:16, #23 Counter in file 0 42:5 -> 45:6, #24 Counter in file 0 47:5 -> 50:6, #25 -Counter in file 0 50:6 -> 50:7, (#24 + 0) Counter in file 0 52:8 -> 52:16, #26 Counter in file 0 52:17 -> 54:6, #27 Counter in file 0 54:6 -> 54:7, #28 Counter in file 0 56:8 -> 56:15, #29 Counter in file 0 56:16 -> 58:6, #30 Counter in file 0 58:12 -> 60:6, #31 -Counter in file 0 60:6 -> 60:7, (#30 + 0) Counter in file 0 61:1 -> 61:2, #32 Emitting segments for file: ../coverage/lazy_boolean.rs Combined regions: @@ -66,14 +64,12 @@ Combined regions: 41:9 -> 41:16 (count=1) 42:5 -> 45:6 (count=1) 47:5 -> 50:6 (count=0) - 50:6 -> 50:7 (count=1) 52:8 -> 52:16 (count=1) 52:17 -> 54:6 (count=0) 54:6 -> 54:7 (count=1) 56:8 -> 56:15 (count=1) 56:16 -> 58:6 (count=1) 58:12 -> 60:6 (count=0) - 60:6 -> 60:7 (count=1) 61:1 -> 61:2 (count=1) Segment at 7:9 (count = 1), RegionEntry Segment at 9:42 (count = 0), Skipped @@ -120,8 +116,7 @@ Segment at 41:16 (count = 0), Skipped Segment at 42:5 (count = 1), RegionEntry Segment at 45:6 (count = 0), Skipped Segment at 47:5 (count = 0), RegionEntry -Segment at 50:6 (count = 1), RegionEntry -Segment at 50:7 (count = 0), Skipped +Segment at 50:6 (count = 0), Skipped Segment at 52:8 (count = 1), RegionEntry Segment at 52:16 (count = 0), Skipped Segment at 52:17 (count = 0), RegionEntry @@ -132,7 +127,6 @@ Segment at 56:15 (count = 0), Skipped Segment at 56:16 (count = 1), RegionEntry Segment at 58:6 (count = 0), Skipped Segment at 58:12 (count = 0), RegionEntry -Segment at 60:6 (count = 1), RegionEntry -Segment at 60:7 (count = 0), Skipped +Segment at 60:6 (count = 0), Skipped Segment at 61:1 (count = 1), RegionEntry Segment at 61:2 (count = 0), Skipped diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.loops_and_branches.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.loops_and_branches.txt index ca3b1d61343..3e0bc6e4959 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.loops_and_branches.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.loops_and_branches.txt @@ -7,7 +7,6 @@ Counter in file 0 15:31 -> 15:32, #8 Counter in file 0 17:10 -> 17:11, #10 Counter in file 0 18:9 -> 18:15, #11 Counter in file 0 19:5 -> 19:6, #12 -Counter in file 0 19:5 -> 19:6, (#8 + 0) Counter in file 0 22:11 -> 25:2, #1 Emitting segments for file: ../coverage/loops_and_branches.rs Combined regions: diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.nested_loops.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.nested_loops.txt index 9c9c46a0834..a19f6253316 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.nested_loops.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.nested_loops.txt @@ -14,10 +14,8 @@ Counter in file 0 17:21 -> 17:33, #10 Counter in file 0 19:21 -> 21:14, #11 Counter in file 0 21:14 -> 21:15, #12 Counter in file 0 22:10 -> 22:11, #13 -Counter in file 0 22:10 -> 22:11, (#3 + 0) Counter in file 0 23:9 -> 23:23, #14 Counter in file 0 24:6 -> 24:7, #15 -Counter in file 0 24:6 -> 24:7, (#1 + 0) Counter in file 0 25:1 -> 25:2, #16 Emitting segments for file: ../coverage/nested_loops.rs Combined regions: @@ -35,9 +33,9 @@ Combined regions: 17:21 -> 17:33 (count=1) 19:21 -> 21:14 (count=0) 21:14 -> 21:15 (count=2) - 22:10 -> 22:11 (count=3) + 22:10 -> 22:11 (count=2) 23:9 -> 23:23 (count=0) - 24:6 -> 24:7 (count=1) + 24:6 -> 24:7 (count=0) 25:1 -> 25:2 (count=1) Segment at 2:9 (count = 1), RegionEntry Segment at 3:27 (count = 0), Skipped @@ -66,11 +64,11 @@ Segment at 17:33 (count = 0), Skipped Segment at 19:21 (count = 0), RegionEntry Segment at 21:14 (count = 2), RegionEntry Segment at 21:15 (count = 0), Skipped -Segment at 22:10 (count = 3), RegionEntry +Segment at 22:10 (count = 2), RegionEntry Segment at 22:11 (count = 0), Skipped Segment at 23:9 (count = 0), RegionEntry Segment at 23:23 (count = 0), Skipped -Segment at 24:6 (count = 1), RegionEntry +Segment at 24:6 (count = 0), RegionEntry Segment at 24:7 (count = 0), Skipped Segment at 25:1 (count = 1), RegionEntry Segment at 25:2 (count = 0), Skipped diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.partial_eq_counter_without_region.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.partial_eq_counter_without_region.txt index dbcaa57b4b2..a444ea44901 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.partial_eq_counter_without_region.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.partial_eq_counter_without_region.txt @@ -2,8 +2,7 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/ Counter in file 0 4:39 -> 4:49, #1 Counter in file 0 4:39 -> 4:49, #2 Counter in file 0 4:39 -> 4:49, #3 -Counter in file 0 4:39 -> 4:49, #4 -Counter in file 0 4:48 -> 4:49, #5 +Counter in file 0 4:48 -> 4:49, #4 Counter in file 0 8:5 -> 8:17, #1 Counter in file 0 21:11 -> 26:2, #1 Counter in file 0 4:39 -> 4:40, #1 @@ -20,8 +19,7 @@ Counter in file 0 4:32 -> 4:33, #5 Counter in file 0 4:51 -> 4:54, #1 Counter in file 0 4:51 -> 4:54, #2 Counter in file 0 4:51 -> 4:54, #3 -Counter in file 0 4:51 -> 4:54, #4 -Counter in file 0 4:53 -> 4:54, #5 +Counter in file 0 4:53 -> 4:54, #4 Counter in file 0 13:9 -> 18:6, #1 Counter in file 0 7:5 -> 7:6, #1 Counter in file 0 4:39 -> 4:40, #1 diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.try_error_result.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.try_error_result.txt index 10fc52354b9..25e1c8930bc 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.try_error_result.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.try_error_result.txt @@ -10,21 +10,18 @@ Counter in file 0 31:42 -> 31:43, #8 Counter in file 0 32:10 -> 32:11, #9 Counter in file 0 32:10 -> 32:11, #10 Counter in file 0 33:6 -> 33:7, #11 -Counter in file 0 33:6 -> 33:7, (#1 + 0) Counter in file 0 34:5 -> 34:11, #12 Counter in file 0 35:1 -> 35:2, #13 Counter in file 0 35:1 -> 35:2, #14 Counter in file 0 5:8 -> 5:20, #1 Counter in file 0 6:9 -> 6:16, #2 Counter in file 0 8:9 -> 8:15, #3 -Counter in file 0 9:6 -> 9:7, (#2 + 0) Counter in file 0 10:1 -> 10:2, #4 Emitting segments for file: ../coverage/try_error_result.rs Combined regions: 5:8 -> 5:20 (count=6) 6:9 -> 6:16 (count=1) 8:9 -> 8:15 (count=5) - 9:6 -> 9:7 (count=1) 10:1 -> 10:2 (count=6) 13:9 -> 14:23 (count=1) 17:9 -> 17:10 (count=6) @@ -35,7 +32,7 @@ Combined regions: 31:13 -> 31:42 (count=5) 31:42 -> 31:43 (count=0) 32:10 -> 32:11 (count=5) - 33:6 -> 33:7 (count=6) + 33:6 -> 33:7 (count=5) 34:5 -> 34:11 (count=0) 35:1 -> 35:2 (count=2) Segment at 5:8 (count = 6), RegionEntry @@ -44,8 +41,6 @@ Segment at 6:9 (count = 1), RegionEntry Segment at 6:16 (count = 0), Skipped Segment at 8:9 (count = 5), RegionEntry Segment at 8:15 (count = 0), Skipped -Segment at 9:6 (count = 1), RegionEntry -Segment at 9:7 (count = 0), Skipped Segment at 10:1 (count = 6), RegionEntry Segment at 10:2 (count = 0), Skipped Segment at 13:9 (count = 1), RegionEntry @@ -64,7 +59,7 @@ Segment at 31:42 (count = 0), RegionEntry Segment at 31:43 (count = 0), Skipped Segment at 32:10 (count = 5), RegionEntry Segment at 32:11 (count = 0), Skipped -Segment at 33:6 (count = 6), RegionEntry +Segment at 33:6 (count = 5), RegionEntry Segment at 33:7 (count = 0), Skipped Segment at 34:5 (count = 0), RegionEntry Segment at 34:11 (count = 0), Skipped diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.while.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.while.txt index 1aad1a3c83b..b75a88b2e92 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.while.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.while.txt @@ -2,21 +2,18 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/ Counter in file 0 2:9 -> 2:16, #1 Counter in file 0 3:11 -> 3:20, #2 Counter in file 0 3:21 -> 4:6, #3 -Counter in file 0 4:6 -> 4:7, (#3 + 0) Counter in file 0 5:1 -> 5:2, #4 Emitting segments for file: ../coverage/while.rs Combined regions: 2:9 -> 2:16 (count=1) 3:11 -> 3:20 (count=1) 3:21 -> 4:6 (count=0) - 4:6 -> 4:7 (count=0) 5:1 -> 5:2 (count=1) Segment at 2:9 (count = 1), RegionEntry Segment at 2:16 (count = 0), Skipped Segment at 3:11 (count = 1), RegionEntry Segment at 3:20 (count = 0), Skipped Segment at 3:21 (count = 0), RegionEntry -Segment at 4:6 (count = 0), RegionEntry -Segment at 4:7 (count = 0), Skipped +Segment at 4:6 (count = 0), Skipped Segment at 5:1 (count = 1), RegionEntry Segment at 5:2 (count = 0), Skipped diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.while_early_return.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.while_early_return.txt index 7c24ea22d67..908613018a4 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.while_early_return.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.while_early_return.txt @@ -5,7 +5,6 @@ Counter in file 0 12:13 -> 14:14, #3 Counter in file 0 18:21 -> 20:22, #4 Counter in file 0 22:21 -> 22:27, #5 Counter in file 0 26:21 -> 26:27, #6 -Counter in file 0 27:18 -> 27:19, (#5 + 0) Counter in file 0 30:9 -> 32:10, #7 Counter in file 0 35:5 -> 35:11, #8 Counter in file 0 36:1 -> 36:2, #9 @@ -18,7 +17,6 @@ Combined regions: 18:21 -> 20:22 (count=1) 22:21 -> 22:27 (count=0) 26:21 -> 26:27 (count=1) - 27:18 -> 27:19 (count=0) 30:9 -> 32:10 (count=6) 35:5 -> 35:11 (count=0) 36:1 -> 36:2 (count=2) @@ -34,8 +32,6 @@ Segment at 22:21 (count = 0), RegionEntry Segment at 22:27 (count = 0), Skipped Segment at 26:21 (count = 1), RegionEntry Segment at 26:27 (count = 0), Skipped -Segment at 27:18 (count = 0), RegionEntry -Segment at 27:19 (count = 0), Skipped Segment at 30:9 (count = 6), RegionEntry Segment at 32:10 (count = 0), Skipped Segment at 35:5 (count = 0), RegionEntry diff --git a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.lazy_boolean/lazy_boolean.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.lazy_boolean/lazy_boolean.main.-------.InstrumentCoverage.0.html index 636341055dc..cd23e4220cf 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.lazy_boolean/lazy_boolean.main.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.lazy_boolean/lazy_boolean.main.-------.InstrumentCoverage.0.html @@ -188,32 +188,32 @@ ; }⦉@29@28,30⦊⦉@28,30 +47:5-50:6: @29[1]: _42 = const ()"> }⦉@29 - if if @31⦊!is_true⦉@31 @31⦊!is_true⦉@31 @32,34⦊{ - a = 2; - }⦉@32,34@33⦊⦉@33 +54:6-54:6: @34.Goto: goto -> bb35"> }⦉@32,34@33⦊⦉@33 - if @35⦊is_true⦉@35 if @35⦊is_true⦉@35 @36,38⦊{ - b = 30; - }⦉@36,38 else }⦉@36,38 else @37⦊{ - c = 400; - }⦉@37@36,38⦊⦉@36,38 + }⦉@37 }@39⦊⦉@39 diff --git a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.loops_and_branches/loops_and_branches.{impl#0}-fmt.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.loops_and_branches/loops_and_branches.{impl#0}-fmt.-------.InstrumentCoverage.0.html index 1b9767506f2..2164a565e22 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.loops_and_branches/loops_and_branches.{impl#0}-fmt.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.loops_and_branches/loops_and_branches.{impl#0}-fmt.-------.InstrumentCoverage.0.html @@ -89,6 +89,6 @@ }⦉@2@15⦊⦉@15 @21⦊Ok(())⦉@21 - }@16,18,19,20⦊⦉@16,18,19,20@22⦊⦉@22 + }@22⦊⦉@22 diff --git a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.nested_loops/nested_loops.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.nested_loops/nested_loops.main.-------.InstrumentCoverage.0.html index 042845b70cc..b30a5a9f81e 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.nested_loops/nested_loops.main.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.nested_loops/nested_loops.main.-------.InstrumentCoverage.0.html @@ -117,9 +117,9 @@ 21:14-21:14: @29.Goto: goto -> bb30"> } }⦉@29@23⦊⦉@23 - }@6,8,9⦊⦉@6,8,9@30⦊⦉@30 - @32⦊countdown -= 1⦉@32; - }@0,1,2,3⦊⦉@0,1,2,3@7⦊⦉@7 + }@30⦊⦉@30 + @32⦊countdown -= 1⦉@32; + }@7⦊⦉@7 }@33⦊⦉@33 diff --git a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.partial_eq_counter_without_region/partial_eq_counter_without_region.{impl#1}-cmp.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.partial_eq_counter_without_region/partial_eq_counter_without_region.{impl#1}-cmp.-------.InstrumentCoverage.0.html index a39772288a3..469a00f6206 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.partial_eq_counter_without_region/partial_eq_counter_without_region.{impl#1}-cmp.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.partial_eq_counter_without_region/partial_eq_counter_without_region.{impl#1}-cmp.-------.InstrumentCoverage.0.html @@ -60,11 +60,7 @@
@14⦊@11,12⦊@10⦊@13⦊Ord⦉@13⦉@10@11,12⦊@13⦊Ord⦉@13⦉@11,12⦉@14@15⦊⦉@15
diff --git a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.partial_eq_counter_without_region/partial_eq_counter_without_region.{impl#2}-partial_cmp.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.partial_eq_counter_without_region/partial_eq_counter_without_region.{impl#2}-partial_cmp.-------.InstrumentCoverage.0.html index 2c03e967eeb..feae343bbbb 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.partial_eq_counter_without_region/partial_eq_counter_without_region.{impl#2}-partial_cmp.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.partial_eq_counter_without_region/partial_eq_counter_without_region.{impl#2}-partial_cmp.-------.InstrumentCoverage.0.html @@ -61,11 +61,7 @@
@17⦊@14,15⦊@12⦊@16⦊PartialOrd⦉@16⦉@12@14,15⦊@16⦊PartialOrd⦉@16⦉@14,15⦉@17@18⦊⦉@18
diff --git a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.tight_infinite_loop/tight_infinite_loop.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.tight_infinite_loop/tight_infinite_loop.main.-------.InstrumentCoverage.0.html index db08315baa6..cc5e54f87ce 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.tight_infinite_loop/tight_infinite_loop.main.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.tight_infinite_loop/tight_infinite_loop.main.-------.InstrumentCoverage.0.html @@ -63,8 +63,8 @@ if @0⦊false⦉@0 { @4,5⦊loop {}⦉@4,5@1,3⦊⦉@1,3@4,5⦊⦉@4,5 +3:14-3:16: @5[0]: _3 = const ()">@4,5⦊loop {}⦉@4,5
@1,3⦊⦉@1,3 } -}@2⦊⦉@2 +}@2⦊⦉@2 diff --git a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.try_error_result/try_error_result.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.try_error_result/try_error_result.main.-------.InstrumentCoverage.0.html index 428c6fadc27..c273c8c88e6 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.try_error_result/try_error_result.main.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.try_error_result/try_error_result.main.-------.InstrumentCoverage.0.html @@ -107,9 +107,9 @@ 31:42-31:43: @26[4]: _36 = _33 31:42-31:43: @26.Call: _35 = <() as From<()>>::from(move _36) -> [return: bb27, unwind: bb32]">@24,26,27,28⦊?⦉@24,26,27,28; }@15⦊⦉@15@23⦊⦉@23 - }@0,1⦊⦉@0,1@29⦊⦉@29 - }@29⦊⦉@29 + @5⦊Ok(())⦉@5 -}@30⦊⦉@30@31⦊⦉@31 +}@30⦊⦉@30@31⦊⦉@31 diff --git a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.while/while.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.while/while.main.-------.InstrumentCoverage.0.html index 5c49ec19707..49b8bb5520d 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.while/while.main.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.while/while.main.-------.InstrumentCoverage.0.html @@ -65,7 +65,7 @@ while @1,2⦊num >= 10⦉@1,2 @3,5⦊{ - }⦉@3,5@3,5⦊⦉@3,5 + }⦉@3,5 }@4⦊⦉@4 diff --git a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.while_early_return/while_early_return.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.while_early_return/while_early_return.main.-------.InstrumentCoverage.0.html index be674dc7d38..3d75e61b800 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.while_early_return/while_early_return.main.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.while_early_return/while_early_return.main.-------.InstrumentCoverage.0.html @@ -102,16 +102,16 @@ else { @10⦊Err(1)⦉@10 - }@9,11⦊⦉@9,11 + } ; } - @12⦊countdown - -= - 1⦉@12 + @12⦊countdown + -= + 1⦉@12 ; } - @4⦊Ok(())⦉@4 -}@13⦊⦉@13@14⦊⦉@14 +}@13⦊⦉@13@14⦊⦉@14 diff --git a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.lazy_boolean/lazy_boolean.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.lazy_boolean/lazy_boolean.main.-------.InstrumentCoverage.0.html index 636341055dc..cd23e4220cf 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.lazy_boolean/lazy_boolean.main.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.lazy_boolean/lazy_boolean.main.-------.InstrumentCoverage.0.html @@ -188,32 +188,32 @@ ; }⦉@29@28,30⦊⦉@28,30 +47:5-50:6: @29[1]: _42 = const ()"> }⦉@29 - if if @31⦊!is_true⦉@31 @31⦊!is_true⦉@31 @32,34⦊{ - a = 2; - }⦉@32,34@33⦊⦉@33 +54:6-54:6: @34.Goto: goto -> bb35"> }⦉@32,34@33⦊⦉@33 - if @35⦊is_true⦉@35 if @35⦊is_true⦉@35 @36,38⦊{ - b = 30; - }⦉@36,38 else }⦉@36,38 else @37⦊{ - c = 400; - }⦉@37@36,38⦊⦉@36,38 + }⦉@37 }@39⦊⦉@39 diff --git a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.loops_and_branches/loops_and_branches.{impl#0}-fmt.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.loops_and_branches/loops_and_branches.{impl#0}-fmt.-------.InstrumentCoverage.0.html index 1b9767506f2..2164a565e22 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.loops_and_branches/loops_and_branches.{impl#0}-fmt.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.loops_and_branches/loops_and_branches.{impl#0}-fmt.-------.InstrumentCoverage.0.html @@ -89,6 +89,6 @@ }⦉@2@15⦊⦉@15 @21⦊Ok(())⦉@21 - }@16,18,19,20⦊⦉@16,18,19,20@22⦊⦉@22 + }@22⦊⦉@22 diff --git a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.nested_loops/nested_loops.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.nested_loops/nested_loops.main.-------.InstrumentCoverage.0.html index 042845b70cc..b30a5a9f81e 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.nested_loops/nested_loops.main.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.nested_loops/nested_loops.main.-------.InstrumentCoverage.0.html @@ -117,9 +117,9 @@ 21:14-21:14: @29.Goto: goto -> bb30"> } }⦉@29@23⦊⦉@23 - }@6,8,9⦊⦉@6,8,9@30⦊⦉@30 - @32⦊countdown -= 1⦉@32; - }@0,1,2,3⦊⦉@0,1,2,3@7⦊⦉@7 + }@30⦊⦉@30 + @32⦊countdown -= 1⦉@32; + }@7⦊⦉@7 }@33⦊⦉@33 diff --git a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.partial_eq_counter_without_region/partial_eq_counter_without_region.{impl#1}-cmp.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.partial_eq_counter_without_region/partial_eq_counter_without_region.{impl#1}-cmp.-------.InstrumentCoverage.0.html index a39772288a3..469a00f6206 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.partial_eq_counter_without_region/partial_eq_counter_without_region.{impl#1}-cmp.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.partial_eq_counter_without_region/partial_eq_counter_without_region.{impl#1}-cmp.-------.InstrumentCoverage.0.html @@ -60,11 +60,7 @@
@14⦊@11,12⦊@10⦊@13⦊Ord⦉@13⦉@10@11,12⦊@13⦊Ord⦉@13⦉@11,12⦉@14@15⦊⦉@15
diff --git a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.partial_eq_counter_without_region/partial_eq_counter_without_region.{impl#2}-partial_cmp.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.partial_eq_counter_without_region/partial_eq_counter_without_region.{impl#2}-partial_cmp.-------.InstrumentCoverage.0.html index 2c03e967eeb..feae343bbbb 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.partial_eq_counter_without_region/partial_eq_counter_without_region.{impl#2}-partial_cmp.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.partial_eq_counter_without_region/partial_eq_counter_without_region.{impl#2}-partial_cmp.-------.InstrumentCoverage.0.html @@ -61,11 +61,7 @@
@17⦊@14,15⦊@12⦊@16⦊PartialOrd⦉@16⦉@12@14,15⦊@16⦊PartialOrd⦉@16⦉@14,15⦉@17@18⦊⦉@18
diff --git a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.tight_infinite_loop/tight_infinite_loop.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.tight_infinite_loop/tight_infinite_loop.main.-------.InstrumentCoverage.0.html index db08315baa6..cc5e54f87ce 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.tight_infinite_loop/tight_infinite_loop.main.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.tight_infinite_loop/tight_infinite_loop.main.-------.InstrumentCoverage.0.html @@ -63,8 +63,8 @@ if @0⦊false⦉@0 { @4,5⦊loop {}⦉@4,5@1,3⦊⦉@1,3@4,5⦊⦉@4,5 +3:14-3:16: @5[0]: _3 = const ()">@4,5⦊loop {}⦉@4,5
@1,3⦊⦉@1,3 } -}@2⦊⦉@2 +}@2⦊⦉@2 diff --git a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.try_error_result/try_error_result.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.try_error_result/try_error_result.main.-------.InstrumentCoverage.0.html index 428c6fadc27..c273c8c88e6 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.try_error_result/try_error_result.main.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.try_error_result/try_error_result.main.-------.InstrumentCoverage.0.html @@ -107,9 +107,9 @@ 31:42-31:43: @26[4]: _36 = _33 31:42-31:43: @26.Call: _35 = <() as From<()>>::from(move _36) -> [return: bb27, unwind: bb32]">@24,26,27,28⦊?⦉@24,26,27,28; }@15⦊⦉@15@23⦊⦉@23 - }@0,1⦊⦉@0,1@29⦊⦉@29 - }@29⦊⦉@29 + @5⦊Ok(())⦉@5 -}@30⦊⦉@30@31⦊⦉@31 +}@30⦊⦉@30@31⦊⦉@31 diff --git a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.while/while.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.while/while.main.-------.InstrumentCoverage.0.html index 5c49ec19707..49b8bb5520d 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.while/while.main.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.while/while.main.-------.InstrumentCoverage.0.html @@ -65,7 +65,7 @@ while @1,2⦊num >= 10⦉@1,2 @3,5⦊{ - }⦉@3,5@3,5⦊⦉@3,5 + }⦉@3,5 }@4⦊⦉@4 diff --git a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.while_early_return/while_early_return.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.while_early_return/while_early_return.main.-------.InstrumentCoverage.0.html index be674dc7d38..3d75e61b800 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.while_early_return/while_early_return.main.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.while_early_return/while_early_return.main.-------.InstrumentCoverage.0.html @@ -102,16 +102,16 @@ else { @10⦊Err(1)⦉@10 - }@9,11⦊⦉@9,11 + } ; } - @12⦊countdown - -= - 1⦉@12 + @12⦊countdown + -= + 1⦉@12 ; } - @4⦊Ok(())⦉@4 -}@13⦊⦉@13@14⦊⦉@14 +}@13⦊⦉@13@14⦊⦉@14 -- cgit 1.4.1-3-g733a5 From 3291d28e9ac1173f033d240bc5f3f145c9c8dd59 Mon Sep 17 00:00:00 2001 From: Rich Kadel Date: Thu, 22 Oct 2020 20:28:16 -0700 Subject: Adds coverage graphviz --- .../rustc_mir/src/transform/coverage/counters.rs | 37 ++- compiler/rustc_mir/src/transform/coverage/debug.rs | 365 ++++++++++++++++++++- compiler/rustc_mir/src/transform/coverage/mod.rs | 34 +- compiler/rustc_mir/src/transform/coverage/spans.rs | 8 + compiler/rustc_mir/src/util/generic_graphviz.rs | 185 +++++++++++ compiler/rustc_mir/src/util/mod.rs | 1 + .../coverage_graphviz.bar.InstrumentCoverage.0.dot | 6 + ...coverage_graphviz.main.InstrumentCoverage.0.dot | 11 + src/test/mir-opt/coverage_graphviz.rs | 20 ++ 9 files changed, 657 insertions(+), 10 deletions(-) create mode 100644 compiler/rustc_mir/src/util/generic_graphviz.rs create mode 100644 src/test/mir-opt/coverage_graphviz.bar.InstrumentCoverage.0.dot create mode 100644 src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot create mode 100644 src/test/mir-opt/coverage_graphviz.rs (limited to 'compiler/rustc_mir/src/transform/coverage/debug.rs') diff --git a/compiler/rustc_mir/src/transform/coverage/counters.rs b/compiler/rustc_mir/src/transform/coverage/counters.rs index 511ad937c24..c31f401780e 100644 --- a/compiler/rustc_mir/src/transform/coverage/counters.rs +++ b/compiler/rustc_mir/src/transform/coverage/counters.rs @@ -1,3 +1,7 @@ +use super::debug; + +use debug::DebugCounters; + use rustc_middle::mir::coverage::*; /// Manages the counter and expression indexes/IDs to generate `CoverageKind` components for MIR @@ -6,6 +10,7 @@ pub(crate) struct CoverageCounters { function_source_hash: u64, next_counter_id: u32, num_expressions: u32, + pub debug_counters: DebugCounters, } impl CoverageCounters { @@ -14,24 +19,46 @@ impl CoverageCounters { function_source_hash, next_counter_id: CounterValueReference::START.as_u32(), num_expressions: 0, + debug_counters: DebugCounters::new(), } } - pub fn make_counter(&mut self) -> CoverageKind { - CoverageKind::Counter { + /// Activate the `DebugCounters` data structures, to provide additional debug formatting + /// features when formating `CoverageKind` (counter) values. + pub fn enable_debug(&mut self) { + self.debug_counters.enable(); + } + + pub fn make_counter(&mut self, debug_block_label_fn: F) -> CoverageKind + where + F: Fn() -> Option, + { + let counter = CoverageKind::Counter { function_source_hash: self.function_source_hash, id: self.next_counter(), + }; + if self.debug_counters.is_enabled() { + self.debug_counters.add_counter(&counter, (debug_block_label_fn)()); } + counter } - pub fn make_expression( + pub fn make_expression( &mut self, lhs: ExpressionOperandId, op: Op, rhs: ExpressionOperandId, - ) -> CoverageKind { + debug_block_label_fn: F, + ) -> CoverageKind + where + F: Fn() -> Option, + { let id = self.next_expression(); - CoverageKind::Expression { id, lhs, op, rhs } + let expression = CoverageKind::Expression { id, lhs, op, rhs }; + if self.debug_counters.is_enabled() { + self.debug_counters.add_counter(&expression, (debug_block_label_fn)()); + } + expression } /// Counter IDs start from one and go up. diff --git a/compiler/rustc_mir/src/transform/coverage/debug.rs b/compiler/rustc_mir/src/transform/coverage/debug.rs index 7eb2d33453c..fbf2ad224a8 100644 --- a/compiler/rustc_mir/src/transform/coverage/debug.rs +++ b/compiler/rustc_mir/src/transform/coverage/debug.rs @@ -1,12 +1,294 @@ -use super::graph::CoverageGraph; +use super::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph}; use super::spans::CoverageSpan; +use crate::util::generic_graphviz::GraphvizWriter; use crate::util::pretty; use crate::util::spanview::{self, SpanViewable}; -use rustc_middle::mir::{self, TerminatorKind}; +use rustc_data_structures::fx::FxHashMap; +use rustc_index::vec::Idx; +use rustc_middle::mir::coverage::*; +use rustc_middle::mir::{self, BasicBlock, TerminatorKind}; use rustc_middle::ty::TyCtxt; +use std::lazy::SyncOnceCell; + +const RUSTC_COVERAGE_DEBUG_OPTIONS: &str = "RUSTC_COVERAGE_DEBUG_OPTIONS"; + +pub(crate) fn debug_options<'a>() -> &'a DebugOptions { + static DEBUG_OPTIONS: SyncOnceCell = SyncOnceCell::new(); + + &DEBUG_OPTIONS.get_or_init(|| DebugOptions::new()) +} + +/// Parses and maintains coverage-specific debug options captured from the environment variable +/// "RUSTC_COVERAGE_DEBUG_OPTIONS", if set. Options can be set on the command line by, for example: +/// +/// $ RUSTC_COVERAGE_DEBUG_OPTIONS=counter-format=block cargo build +#[derive(Debug, Clone)] +pub(crate) struct DebugOptions { + counter_format: ExpressionFormat, +} + +impl DebugOptions { + fn new() -> Self { + let mut counter_format = ExpressionFormat::default(); + + if let Ok(env_debug_options) = std::env::var(RUSTC_COVERAGE_DEBUG_OPTIONS) { + for setting_str in env_debug_options.replace(" ", "").replace("-", "_").split(",") { + let mut setting = setting_str.splitn(2, "="); + match setting.next() { + Some(option) if option == "counter_format" => { + if let Some(strval) = setting.next() { + counter_format = counter_format_option_val(strval); + debug!( + "{} env option `counter_format` is set to {:?}", + RUSTC_COVERAGE_DEBUG_OPTIONS, counter_format + ); + } else { + bug!( + "`{}` option in environment variable {} requires one or more \ + plus-separated choices (a non-empty subset of \ + `id+block+operation`)", + option, + RUSTC_COVERAGE_DEBUG_OPTIONS + ); + } + } + Some("") => {} + Some(invalid) => bug!( + "Unsupported setting `{}` in environment variable {}", + invalid, + RUSTC_COVERAGE_DEBUG_OPTIONS + ), + None => {} + } + } + } + + Self { counter_format } + } +} + +fn counter_format_option_val(strval: &str) -> ExpressionFormat { + let mut counter_format = ExpressionFormat { id: false, block: false, operation: false }; + let components = strval.splitn(3, "+"); + for component in components { + match component { + "id" => counter_format.id = true, + "block" => counter_format.block = true, + "operation" => counter_format.operation = true, + _ => bug!( + "Unsupported counter_format choice `{}` in environment variable {}", + component, + RUSTC_COVERAGE_DEBUG_OPTIONS + ), + } + } + counter_format +} + +#[derive(Debug, Clone)] +struct ExpressionFormat { + id: bool, + block: bool, + operation: bool, +} + +impl Default for ExpressionFormat { + fn default() -> Self { + Self { id: false, block: true, operation: true } + } +} + +/// If enabled, this struct maintains a map from `CoverageKind` IDs (as `ExpressionOperandId`) to +/// the `CoverageKind` data and optional label (normally, the counter's associated +/// `BasicCoverageBlock` format string, if any). +/// +/// Use `format_counter` to convert one of these `CoverageKind` counters to a debug output string, +/// as directed by the `DebugOptions`. This allows the format of counter labels in logs and dump +/// files (including the `CoverageGraph` graphviz file) to be changed at runtime, via environment +/// variable. +/// +/// `DebugCounters` supports a recursive rendering of `Expression` counters, so they can be +/// presented as nested expressions such as `(bcb3 - (bcb0 + bcb1))`. +pub(crate) struct DebugCounters { + some_counters: Option>, +} + +impl DebugCounters { + pub fn new() -> Self { + Self { some_counters: None } + } + + pub fn enable(&mut self) { + self.some_counters.replace(FxHashMap::default()); + } + + pub fn is_enabled(&mut self) -> bool { + self.some_counters.is_some() + } + + pub fn add_counter(&mut self, counter_kind: &CoverageKind, some_block_label: Option) { + if let Some(counters) = &mut self.some_counters { + let id: ExpressionOperandId = match *counter_kind { + CoverageKind::Counter { id, .. } => id.into(), + CoverageKind::Expression { id, .. } => id.into(), + _ => bug!( + "the given `CoverageKind` is not an counter or expression: {:?}", + counter_kind + ), + }; + counters + .insert(id.into(), DebugCounter::new(counter_kind.clone(), some_block_label)) + .expect_none( + "attempt to add the same counter_kind to DebugCounters more than once", + ); + } + } + + pub fn format_counter(&self, counter_kind: &CoverageKind) -> String { + match *counter_kind { + CoverageKind::Counter { .. } => { + format!("Counter({})", self.format_counter_kind(counter_kind)) + } + CoverageKind::Expression { .. } => { + format!("Expression({})", self.format_counter_kind(counter_kind)) + } + CoverageKind::Unreachable { .. } => "Unreachable".to_owned(), + } + } + + fn format_counter_kind(&self, counter_kind: &CoverageKind) -> String { + let counter_format = &debug_options().counter_format; + if let CoverageKind::Expression { id, lhs, op, rhs } = *counter_kind { + if counter_format.operation { + return format!( + "{}{} {} {}", + if counter_format.id || self.some_counters.is_none() { + format!("#{} = ", id.index()) + } else { + String::new() + }, + self.format_operand(lhs), + if op == Op::Add { "+" } else { "-" }, + self.format_operand(rhs), + ); + } + } + + let id: ExpressionOperandId = match *counter_kind { + CoverageKind::Counter { id, .. } => id.into(), + CoverageKind::Expression { id, .. } => id.into(), + _ => { + bug!("the given `CoverageKind` is not an counter or expression: {:?}", counter_kind) + } + }; + if self.some_counters.is_some() && (counter_format.block || !counter_format.id) { + let counters = self.some_counters.as_ref().unwrap(); + if let Some(DebugCounter { some_block_label: Some(block_label), .. }) = + counters.get(&id.into()) + { + return if counter_format.id { + format!("{}#{}", block_label, id.index()) + } else { + format!("{}", block_label) + }; + } + } + format!("#{}", id.index()) + } + + fn format_operand(&self, operand: ExpressionOperandId) -> String { + if operand.index() == 0 { + return String::from("0"); + } + if let Some(counters) = &self.some_counters { + if let Some(DebugCounter { counter_kind, some_block_label }) = counters.get(&operand) { + if let CoverageKind::Expression { .. } = counter_kind { + if let Some(block_label) = some_block_label { + if debug_options().counter_format.block { + return format!( + "{}:({})", + block_label, + self.format_counter_kind(counter_kind) + ); + } + } + return format!("({})", self.format_counter_kind(counter_kind)); + } + return format!("{}", self.format_counter_kind(counter_kind)); + } + } + format!("#{}", operand.index().to_string()) + } +} + +/// A non-public support class to `DebugCounters`. +#[derive(Debug)] +struct DebugCounter { + counter_kind: CoverageKind, + some_block_label: Option, +} + +impl DebugCounter { + fn new(counter_kind: CoverageKind, some_block_label: Option) -> Self { + Self { counter_kind, some_block_label } + } +} + +/// If enabled, this data structure captures additional debugging information used when generating +/// a Graphviz (.dot file) representation of the `CoverageGraph`, for debugging purposes. +pub(crate) struct GraphvizData { + some_bcb_to_coverage_spans_with_counters: + Option>>, + some_edge_to_counter: Option>, +} + +impl GraphvizData { + pub fn new() -> Self { + Self { some_bcb_to_coverage_spans_with_counters: None, some_edge_to_counter: None } + } + + pub fn enable(&mut self) { + self.some_bcb_to_coverage_spans_with_counters = Some(FxHashMap::default()); + self.some_edge_to_counter = Some(FxHashMap::default()); + } + + pub fn is_enabled(&mut self) -> bool { + self.some_bcb_to_coverage_spans_with_counters.is_some() + } + + pub fn add_bcb_coverage_span_with_counter( + &mut self, + bcb: BasicCoverageBlock, + coverage_span: &CoverageSpan, + counter_kind: &CoverageKind, + ) { + if let Some(bcb_to_coverage_spans_with_counters) = + self.some_bcb_to_coverage_spans_with_counters.as_mut() + { + bcb_to_coverage_spans_with_counters + .entry(bcb) + .or_insert_with(|| Vec::new()) + .push((coverage_span.clone(), counter_kind.clone())); + } + } + + pub fn get_bcb_coverage_spans_with_counters( + &self, + bcb: BasicCoverageBlock, + ) -> Option<&Vec<(CoverageSpan, CoverageKind)>> { + if let Some(bcb_to_coverage_spans_with_counters) = + self.some_bcb_to_coverage_spans_with_counters.as_ref() + { + bcb_to_coverage_spans_with_counters.get(&bcb) + } else { + None + } + } +} + /// Generates the MIR pass `CoverageSpan`-specific spanview dump file. pub(crate) fn dump_coverage_spanview( tcx: TyCtxt<'tcx>, @@ -47,6 +329,85 @@ fn span_viewables( span_viewables } +/// Generates the MIR pass coverage-specific graphviz dump file. +pub(crate) fn dump_coverage_graphviz( + tcx: TyCtxt<'tcx>, + mir_body: &mir::Body<'tcx>, + pass_name: &str, + basic_coverage_blocks: &CoverageGraph, + debug_counters: &DebugCounters, + graphviz_data: &GraphvizData, +) { + let mir_source = mir_body.source; + let def_id = mir_source.def_id(); + let node_content = |bcb| { + bcb_to_string_sections( + tcx, + mir_body, + debug_counters, + &basic_coverage_blocks[bcb], + graphviz_data.get_bcb_coverage_spans_with_counters(bcb), + ) + }; + let edge_labels = |from_bcb| { + let from_bcb_data = &basic_coverage_blocks[from_bcb]; + let from_terminator = from_bcb_data.terminator(mir_body); + from_terminator + .kind + .fmt_successor_labels() + .iter() + .map(|label| label.to_string()) + .collect::>() + }; + let graphviz_name = format!("Cov_{}_{}", def_id.krate.index(), def_id.index.index()); + let graphviz_writer = + GraphvizWriter::new(basic_coverage_blocks, &graphviz_name, node_content, edge_labels); + let mut file = pretty::create_dump_file(tcx, "dot", None, pass_name, &0, mir_source) + .expect("Unexpected error creating BasicCoverageBlock graphviz DOT file"); + graphviz_writer + .write_graphviz(tcx, &mut file) + .expect("Unexpected error writing BasicCoverageBlock graphviz DOT file"); +} + +fn bcb_to_string_sections( + tcx: TyCtxt<'tcx>, + mir_body: &mir::Body<'tcx>, + debug_counters: &DebugCounters, + bcb_data: &BasicCoverageBlockData, + some_coverage_spans_with_counters: Option<&Vec<(CoverageSpan, CoverageKind)>>, +) -> Vec { + let len = bcb_data.basic_blocks.len(); + let mut sections = Vec::new(); + if let Some(coverage_spans_with_counters) = some_coverage_spans_with_counters { + sections.push( + coverage_spans_with_counters + .iter() + .map(|(covspan, counter)| { + format!( + "{} at {}", + debug_counters.format_counter(counter), + covspan.format(tcx, mir_body) + ) + }) + .collect::>() + .join("\n"), + ); + } + let non_term_blocks = bcb_data.basic_blocks[0..len - 1] + .iter() + .map(|&bb| format!("{:?}: {}", bb, term_type(&mir_body[bb].terminator().kind))) + .collect::>(); + if non_term_blocks.len() > 0 { + sections.push(non_term_blocks.join("\n")); + } + sections.push(format!( + "{:?}: {}", + bcb_data.basic_blocks.last().unwrap(), + term_type(&bcb_data.terminator(mir_body).kind) + )); + sections +} + /// Returns a simple string representation of a `TerminatorKind` variant, indenpendent of any /// values it might hold. pub(crate) fn term_type(kind: &TerminatorKind<'tcx>) -> &'static str { diff --git a/compiler/rustc_mir/src/transform/coverage/mod.rs b/compiler/rustc_mir/src/transform/coverage/mod.rs index aa5771cfad4..d1d94092c9d 100644 --- a/compiler/rustc_mir/src/transform/coverage/mod.rs +++ b/compiler/rustc_mir/src/transform/coverage/mod.rs @@ -103,6 +103,14 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { debug!("instrumenting {:?}, span: {}", def_id, source_map.span_to_string(body_span)); + let mut graphviz_data = debug::GraphvizData::new(); + + let dump_graphviz = tcx.sess.opts.debugging_opts.dump_mir_graphviz; + if dump_graphviz { + graphviz_data.enable(); + self.coverage_counters.enable_debug(); + } + //////////////////////////////////////////////////// // Compute `CoverageSpan`s from the `CoverageGraph`. let coverage_spans = CoverageSpans::generate_coverage_spans( @@ -121,7 +129,20 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { ); } - self.inject_coverage_span_counters(coverage_spans); + self.inject_coverage_span_counters(coverage_spans, &mut graphviz_data); + + if graphviz_data.is_enabled() { + // Even if there was an error, a partial CoverageGraph can still generate a useful + // graphviz output. + debug::dump_coverage_graphviz( + tcx, + self.mir_body, + self.pass_name, + &self.basic_coverage_blocks, + &self.coverage_counters.debug_counters, + &graphviz_data, + ); + } } /// Inject a counter for each `CoverageSpan`. There can be multiple `CoverageSpan`s for a given @@ -129,7 +150,11 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { /// `bcb` to its `Counter`, when injected. Subsequent `CoverageSpan`s for a BCB that already has /// a `Counter` will inject an `Expression` instead, and compute its value by adding `ZERO` to /// the BCB `Counter` value. - fn inject_coverage_span_counters(&mut self, coverage_spans: Vec) { + fn inject_coverage_span_counters( + &mut self, + coverage_spans: Vec, + graphviz_data: &mut debug::GraphvizData, + ) { let tcx = self.tcx; let source_map = tcx.sess.source_map(); let body_span = self.body_span; @@ -145,6 +170,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { counter_operand, Op::Add, ExpressionOperandId::ZERO, + || Some(format!("{:?}", bcb)), ); debug!( "Injecting counter expression {:?} at: {:?}:\n{}\n==========", @@ -152,11 +178,12 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { span, source_map.span_to_snippet(span).expect("Error getting source for span"), ); + graphviz_data.add_bcb_coverage_span_with_counter(bcb, &covspan, &expression); let bb = self.basic_coverage_blocks[bcb].leader_bb(); let code_region = make_code_region(file_name, &source_file, span, body_span); inject_statement(self.mir_body, expression, bb, Some(code_region)); } else { - let counter = self.coverage_counters.make_counter(); + let counter = self.coverage_counters.make_counter(|| Some(format!("{:?}", bcb))); debug!( "Injecting counter {:?} at: {:?}:\n{}\n==========", counter, @@ -165,6 +192,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { ); let counter_operand = counter.as_operand_id(); bcb_counters[bcb] = Some(counter_operand); + graphviz_data.add_bcb_coverage_span_with_counter(bcb, &covspan, &counter); let bb = self.basic_coverage_blocks[bcb].leader_bb(); let code_region = make_code_region(file_name, &source_file, span, body_span); inject_statement(self.mir_body, counter, bb, Some(code_region)); diff --git a/compiler/rustc_mir/src/transform/coverage/spans.rs b/compiler/rustc_mir/src/transform/coverage/spans.rs index 23531ecf229..61b5b148053 100644 --- a/compiler/rustc_mir/src/transform/coverage/spans.rs +++ b/compiler/rustc_mir/src/transform/coverage/spans.rs @@ -134,6 +134,14 @@ impl CoverageSpan { self.bcb == other.bcb } + pub fn format(&self, tcx: TyCtxt<'tcx>, mir_body: &'a mir::Body<'tcx>) -> String { + format!( + "{}\n {}", + source_range_no_file(tcx, &self.span), + self.format_coverage_statements(tcx, mir_body).replace("\n", "\n "), + ) + } + pub fn format_coverage_statements( &self, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_mir/src/util/generic_graphviz.rs b/compiler/rustc_mir/src/util/generic_graphviz.rs new file mode 100644 index 00000000000..91499bb61c2 --- /dev/null +++ b/compiler/rustc_mir/src/util/generic_graphviz.rs @@ -0,0 +1,185 @@ +use rustc_data_structures::graph::{self, iterate}; +use rustc_graphviz as dot; +use rustc_middle::ty::TyCtxt; +use std::io::{self, Write}; + +pub struct GraphvizWriter< + 'a, + G: graph::DirectedGraph + graph::WithSuccessors + graph::WithStartNode + graph::WithNumNodes, + NodeContentFn: Fn(::Node) -> Vec, + EdgeLabelsFn: Fn(::Node) -> Vec, +> { + graph: &'a G, + is_subgraph: bool, + graphviz_name: String, + graph_label: Option, + node_content_fn: NodeContentFn, + edge_labels_fn: EdgeLabelsFn, +} + +impl< + 'a, + G: graph::DirectedGraph + graph::WithSuccessors + graph::WithStartNode + graph::WithNumNodes, + NodeContentFn: Fn(::Node) -> Vec, + EdgeLabelsFn: Fn(::Node) -> Vec, +> GraphvizWriter<'a, G, NodeContentFn, EdgeLabelsFn> +{ + pub fn new( + graph: &'a G, + graphviz_name: &str, + node_content_fn: NodeContentFn, + edge_labels_fn: EdgeLabelsFn, + ) -> Self { + Self { + graph, + is_subgraph: false, + graphviz_name: graphviz_name.to_owned(), + graph_label: None, + node_content_fn, + edge_labels_fn, + } + } + + pub fn new_subgraph( + graph: &'a G, + graphviz_name: &str, + node_content_fn: NodeContentFn, + edge_labels_fn: EdgeLabelsFn, + ) -> Self { + Self { + graph, + is_subgraph: true, + graphviz_name: graphviz_name.to_owned(), + graph_label: None, + node_content_fn, + edge_labels_fn, + } + } + + pub fn set_graph_label(&mut self, graph_label: &str) { + self.graph_label = Some(graph_label.to_owned()); + } + + /// Write a graphviz DOT of the graph + pub fn write_graphviz<'tcx, W>(&self, tcx: TyCtxt<'tcx>, w: &mut W) -> io::Result<()> + where + W: Write, + { + let kind = if self.is_subgraph { "subgraph" } else { "digraph" }; + let cluster = if self.is_subgraph { "cluster_" } else { "" }; // Print border around graph + // FIXME(richkadel): If/when migrating the MIR graphviz to this generic implementation, + // prepend "Mir_" to the graphviz_safe_def_name(def_id) + writeln!(w, "{} {}{} {{", kind, cluster, self.graphviz_name)?; + + // Global graph properties + let font = format!(r#"fontname="{}""#, tcx.sess.opts.debugging_opts.graphviz_font); + let mut graph_attrs = vec![&font[..]]; + let mut content_attrs = vec![&font[..]]; + + let dark_mode = tcx.sess.opts.debugging_opts.graphviz_dark_mode; + if dark_mode { + graph_attrs.push(r#"bgcolor="black""#); + graph_attrs.push(r#"fontcolor="white""#); + content_attrs.push(r#"color="white""#); + content_attrs.push(r#"fontcolor="white""#); + } + + writeln!(w, r#" graph [{}];"#, graph_attrs.join(" "))?; + let content_attrs_str = content_attrs.join(" "); + writeln!(w, r#" node [{}];"#, content_attrs_str)?; + writeln!(w, r#" edge [{}];"#, content_attrs_str)?; + + // Graph label + if let Some(graph_label) = &self.graph_label { + self.write_graph_label(graph_label, w)?; + } + + // Nodes + for node in iterate::post_order_from(self.graph, self.graph.start_node()) { + self.write_node(node, dark_mode, w)?; + } + + // Edges + for source in iterate::post_order_from(self.graph, self.graph.start_node()) { + self.write_edges(source, w)?; + } + writeln!(w, "}}") + } + + /// Write a graphviz DOT node for the given node. + pub fn write_node(&self, node: G::Node, dark_mode: bool, w: &mut W) -> io::Result<()> + where + W: Write, + { + // Start a new node with the label to follow, in one of DOT's pseudo-HTML tables. + write!(w, r#" {} [shape="none", label=<"#, self.node(node))?; + + write!(w, r#""#)?; + + // FIXME(richkadel): Need generic way to know if node header should have a different color + // let (blk, bgcolor) = if data.is_cleanup { + // (format!("{:?} (cleanup)", node), "lightblue") + // } else { + // let color = if dark_mode { "dimgray" } else { "gray" }; + // (format!("{:?}", node), color) + // }; + let color = if dark_mode { "dimgray" } else { "gray" }; + let (blk, bgcolor) = (format!("{:?}", node), color); + write!( + w, + r#""#, + attrs = r#"align="center""#, + colspan = 1, + blk = blk, + bgcolor = bgcolor + )?; + + for section in (self.node_content_fn)(node) { + write!( + w, + r#""#, + dot::escape_html(§ion).replace("\n", "
") + )?; + } + + // Close the table + write!(w, "
{blk}
{}
")?; + + // Close the node label and the node itself. + writeln!(w, ">];") + } + + /// Write graphviz DOT edges with labels between the given node and all of its successors. + fn write_edges(&self, source: G::Node, w: &mut W) -> io::Result<()> + where + W: Write, + { + let edge_labels = (self.edge_labels_fn)(source); + for (index, target) in self.graph.successors(source).enumerate() { + let src = self.node(source); + let trg = self.node(target); + let escaped_edge_label = if let Some(edge_label) = edge_labels.get(index) { + dot::escape_html(edge_label).replace("\n", r#"
"#) + } else { + "".to_owned() + }; + writeln!(w, r#" {} -> {} [label=<{}>];"#, src, trg, escaped_edge_label)?; + } + Ok(()) + } + + /// Write the graphviz DOT label for the overall graph. This is essentially a block of text that + /// will appear below the graph. + fn write_graph_label(&self, label: &str, w: &mut W) -> io::Result<()> + where + W: Write, + { + let lines = label.split("\n").map(|s| dot::escape_html(s)).collect::>(); + let escaped_label = lines.join(r#"
"#); + writeln!(w, r#" label=<

{}



>;"#, escaped_label) + } + + fn node(&self, node: G::Node) -> String { + format!("{:?}__{}", node, self.graphviz_name) + } +} diff --git a/compiler/rustc_mir/src/util/mod.rs b/compiler/rustc_mir/src/util/mod.rs index 7da2f4ffe08..aaee0bc526d 100644 --- a/compiler/rustc_mir/src/util/mod.rs +++ b/compiler/rustc_mir/src/util/mod.rs @@ -7,6 +7,7 @@ pub mod storage; mod alignment; pub mod collect_writes; mod find_self_call; +pub(crate) mod generic_graphviz; mod graphviz; pub(crate) mod pretty; pub(crate) mod spanview; diff --git a/src/test/mir-opt/coverage_graphviz.bar.InstrumentCoverage.0.dot b/src/test/mir-opt/coverage_graphviz.bar.InstrumentCoverage.0.dot new file mode 100644 index 00000000000..df9f7aa627b --- /dev/null +++ b/src/test/mir-opt/coverage_graphviz.bar.InstrumentCoverage.0.dot @@ -0,0 +1,6 @@ +digraph Cov_0_4 { + graph [fontname="Courier, monospace"]; + node [fontname="Courier, monospace"]; + edge [fontname="Courier, monospace"]; + bcb0__Cov_0_4 [shape="none", label=<
bcb0
Counter(bcb0) at 19:5-20:2
19:5-19:9: @0[0]: _0 = const true
20:2-20:2: @0.Return: return
bb0: Return
>]; +} diff --git a/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot b/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot new file mode 100644 index 00000000000..051ef498fb7 --- /dev/null +++ b/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot @@ -0,0 +1,11 @@ +digraph Cov_0_3 { + graph [fontname="Courier, monospace"]; + node [fontname="Courier, monospace"]; + edge [fontname="Courier, monospace"]; + bcb2__Cov_0_3 [shape="none", label=<
bcb2
Counter(bcb2) at 14:6-14:6
14:6-14:6: @4.Goto: goto -> bb0
bb4: Goto
>]; + bcb1__Cov_0_3 [shape="none", label=<
bcb1
Counter(bcb1) at 12:13-12:18
12:13-12:18: @5[0]: _0 = const ()
Expression(bcb1 + 0) at 15:2-15:2
15:2-15:2: @5.Return: return
bb3: FalseEdge
bb5: Return
>]; + bcb0__Cov_0_3 [shape="none", label=<
bcb0
Counter(bcb0) at 11:12-11:17
11:12-11:17: @1.Call: _2 = bar() -> [return: bb2, unwind: bb6]
11:12-11:17: @2[0]: FakeRead(ForMatchedPlace, _2)
bb0: FalseUnwind
bb1: Call
bb2: SwitchInt
>]; + bcb2__Cov_0_3 -> bcb0__Cov_0_3 [label=<>]; + bcb0__Cov_0_3 -> bcb2__Cov_0_3 [label=]; + bcb0__Cov_0_3 -> bcb1__Cov_0_3 [label=]; +} diff --git a/src/test/mir-opt/coverage_graphviz.rs b/src/test/mir-opt/coverage_graphviz.rs new file mode 100644 index 00000000000..b3c90c52837 --- /dev/null +++ b/src/test/mir-opt/coverage_graphviz.rs @@ -0,0 +1,20 @@ +// Test that `-Z instrument-coverage` with `-Z dump-mir-graphviz` generates a graphviz (.dot file) +// rendering of the `BasicCoverageBlock` coverage control flow graph, with counters and +// expressions. + +// needs-profiler-support +// compile-flags: -Z instrument-coverage -Z dump-mir-graphviz +// EMIT_MIR coverage_graphviz.main.InstrumentCoverage.0.dot +// EMIT_MIR coverage_graphviz.bar.InstrumentCoverage.0.dot +fn main() { + loop { + if bar() { + break; + } + } +} + +#[inline(never)] +fn bar() -> bool { + true +} -- cgit 1.4.1-3-g733a5 From 198ba3bd1cfedc7115f91d549a352da2b25050b7 Mon Sep 17 00:00:00 2001 From: Rich Kadel Date: Thu, 22 Oct 2020 14:30:03 -0700 Subject: Injecting expressions in place of counters where helpful Implementing the Graph traits for the BasicCoverageBlock graph. optimized replacement of counters with expressions plus new BCB graphviz * Avoid adding coverage to unreachable blocks. * Special case for Goto at the end of the body. Make it non-reportable. Improved debugging and formatting options (from env) Don't automatically add counters to BCBs without CoverageSpans. They may still get counters but only if there are dependencies from other BCBs that have spans, I think. Make CodeRegions optional for Counters too. It is possible to inject counters (`llvm.instrprof.increment` intrinsic calls without corresponding code regions in the coverage map. An expression can still uses these counter values. Refactored instrument_coverage.rs -> instrument_coverage/mod.rs, and then broke up the mod into multiple files. Compiling with coverage, with the expression optimization, works on the json5format crate and its dependencies. Refactored debug features from mod.rs to debug.rs --- .../rustc_codegen_llvm/src/coverageinfo/mod.rs | 19 +- compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs | 4 +- .../rustc_codegen_ssa/src/traits/coverageinfo.rs | 10 +- .../rustc_mir/src/transform/coverage/counters.rs | 524 ++++++++++++++++++++- compiler/rustc_mir/src/transform/coverage/debug.rs | 310 +++++++++++- compiler/rustc_mir/src/transform/coverage/graph.rs | 321 ++++++++++++- compiler/rustc_mir/src/transform/coverage/mod.rs | 323 +++++++++++-- .../coverage_graphviz.bar.InstrumentCoverage.0.dot | 2 +- ...coverage_graphviz.main.InstrumentCoverage.0.dot | 4 +- ...nstrument_coverage.main.InstrumentCoverage.diff | 8 +- .../expected_export_coverage.drop_trait.json | 8 +- .../expected_export_coverage.generics.json | 8 +- .../expected_export_coverage.if_else.json | 24 +- .../expected_export_coverage.try_error_result.json | 12 +- ...xpected_export_coverage.various_conditions.json | 12 +- ...xpected_export_coverage.while_early_return.json | 12 +- .../expected_show_coverage.drop_trait.txt | 2 +- .../expected_show_coverage.generics.txt | 2 +- .../expected_show_coverage.if_else.txt | 4 +- .../expected_show_coverage.try_error_result.txt | 2 +- .../expected_show_coverage.various_conditions.txt | 2 +- .../expected_show_coverage.while_early_return.txt | 2 +- .../expected_show_coverage_counters.closure.txt | 16 +- .../expected_show_coverage_counters.drop_trait.txt | 2 +- .../expected_show_coverage_counters.generics.txt | 2 +- .../expected_show_coverage_counters.if.txt | 4 +- .../expected_show_coverage_counters.if_else.txt | 10 +- ...expected_show_coverage_counters.inner_items.txt | 10 +- ...xpected_show_coverage_counters.lazy_boolean.txt | 68 +-- ...d_show_coverage_counters.loops_and_branches.txt | 12 +- ...xpected_show_coverage_counters.nested_loops.txt | 34 +- ...expected_show_coverage_counters.simple_loop.txt | 12 +- ...xpected_show_coverage_counters.simple_match.txt | 24 +- ..._show_coverage_counters.tight_infinite_loop.txt | 2 +- ...ted_show_coverage_counters.try_error_result.txt | 33 +- ...d_show_coverage_counters.various_conditions.txt | 137 +++--- .../expected_show_coverage_counters.while.txt | 6 +- ...d_show_coverage_counters.while_early_return.txt | 21 +- .../expected_export_coverage.drop_trait.json | 8 +- .../expected_export_coverage.generics.json | 8 +- .../expected_export_coverage.if_else.json | 24 +- .../expected_export_coverage.try_error_result.json | 12 +- ...xpected_export_coverage.various_conditions.json | 12 +- ...xpected_export_coverage.while_early_return.json | 12 +- .../expected_show_coverage.drop_trait.txt | 2 +- .../expected_show_coverage.generics.txt | 2 +- .../expected_show_coverage.if_else.txt | 4 +- .../expected_show_coverage.try_error_result.txt | 2 +- .../expected_show_coverage.various_conditions.txt | 2 +- .../expected_show_coverage.while_early_return.txt | 2 +- .../expected_show_coverage_counters.closure.txt | 16 +- .../expected_show_coverage_counters.drop_trait.txt | 2 +- .../expected_show_coverage_counters.generics.txt | 2 +- .../expected_show_coverage_counters.if.txt | 4 +- .../expected_show_coverage_counters.if_else.txt | 10 +- ...expected_show_coverage_counters.inner_items.txt | 10 +- ...xpected_show_coverage_counters.lazy_boolean.txt | 68 +-- ...d_show_coverage_counters.loops_and_branches.txt | 12 +- ...xpected_show_coverage_counters.nested_loops.txt | 34 +- ..._counters.partial_eq_counter_without_region.txt | 20 +- ...expected_show_coverage_counters.simple_loop.txt | 12 +- ...xpected_show_coverage_counters.simple_match.txt | 24 +- ..._show_coverage_counters.tight_infinite_loop.txt | 2 +- ...ted_show_coverage_counters.try_error_result.txt | 33 +- ...d_show_coverage_counters.various_conditions.txt | 137 +++--- .../expected_show_coverage_counters.while.txt | 6 +- ...d_show_coverage_counters.while_early_return.txt | 21 +- ...op_trait.main.-------.InstrumentCoverage.0.html | 2 +- ...generics.main.-------.InstrumentCoverage.0.html | 2 +- .../if_else.main.-------.InstrumentCoverage.0.html | 30 +- ...r_result.call.-------.InstrumentCoverage.0.html | 4 +- ...op_trait.main.-------.InstrumentCoverage.0.html | 2 +- ...generics.main.-------.InstrumentCoverage.0.html | 2 +- .../if_else.main.-------.InstrumentCoverage.0.html | 30 +- ...r_result.call.-------.InstrumentCoverage.0.html | 4 +- 75 files changed, 1984 insertions(+), 603 deletions(-) (limited to 'compiler/rustc_mir/src/transform/coverage/debug.rs') diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index c4b4032fd47..75e8abaf2a9 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -58,7 +58,11 @@ impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { unsafe { llvm::LLVMRustCoverageCreatePGOFuncNameVar(llfn, mangled_fn_name.as_ptr()) } } - fn set_function_source_hash(&mut self, instance: Instance<'tcx>, function_source_hash: u64) -> bool { + fn set_function_source_hash( + &mut self, + instance: Instance<'tcx>, + function_source_hash: u64, + ) -> bool { if let Some(coverage_context) = self.coverage_context() { debug!( "ensuring function source hash is set for instance={:?}; function_source_hash={}", @@ -69,6 +73,7 @@ impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { .entry(instance) .or_insert_with(|| FunctionCoverage::new(self.tcx, instance)) .set_function_source_hash(function_source_hash); + true } else { false } @@ -92,6 +97,7 @@ impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { .entry(instance) .or_insert_with(|| FunctionCoverage::new(self.tcx, instance)) .add_counter(function_source_hash, id, region); + true } else { false } @@ -105,8 +111,8 @@ impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { op: Op, rhs: ExpressionOperandId, region: Option, - ) { - if let Some(coverage_context) = self.coverage_context() -> bool { + ) -> bool { + if let Some(coverage_context) = self.coverage_context() { debug!( "adding counter expression to coverage_map: instance={:?}, id={:?}, {:?} {:?} {:?}; \ region: {:?}", @@ -117,6 +123,7 @@ impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { .entry(instance) .or_insert_with(|| FunctionCoverage::new(self.tcx, instance)) .add_counter_expression(id, lhs, op, rhs, region); + true } else { false } @@ -124,12 +131,16 @@ impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { fn add_coverage_unreachable(&mut self, instance: Instance<'tcx>, region: CodeRegion) -> bool { if let Some(coverage_context) = self.coverage_context() { - debug!("adding unreachable code to coverage_map: instance={:?}, at {:?}", instance, region,); + debug!( + "adding unreachable code to coverage_map: instance={:?}, at {:?}", + instance, region, + ); let mut coverage_map = coverage_context.function_coverage_map.borrow_mut(); coverage_map .entry(instance) .or_insert_with(|| FunctionCoverage::new(self.tcx, instance)) .add_unreachable_region(region); + true } else { false } diff --git a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs index e52f952e932..339e0d95fdf 100644 --- a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs @@ -24,10 +24,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let fn_name = bx.create_pgo_func_name_var(self.instance); let hash = bx.const_u64(function_source_hash); let num_counters = bx.const_u32(coverageinfo.num_counters); - let id = bx.const_u32(u32::from(id)); + let index = bx.const_u32(u32::from(id)); debug!( "codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})", - fn_name, hash, num_counters, id, + fn_name, hash, num_counters, index, ); bx.instrprof_increment(fn_name, hash, num_counters, index); } diff --git a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs index 5aa0950b399..7da38880d60 100644 --- a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs +++ b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs @@ -11,7 +11,11 @@ pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes { /// Returns true if the function source hash was added to the coverage map; false if /// `-Z instrument-coverage` is not enabled (a coverage map is not being generated). - fn set_function_source_hash(&mut self, instance: Instance<'tcx>, function_source_hash: u64) -> bool; + fn set_function_source_hash( + &mut self, + instance: Instance<'tcx>, + function_source_hash: u64, + ) -> bool; /// Returns true if the counter was added to the coverage map; false if `-Z instrument-coverage` /// is not enabled (a coverage map is not being generated). @@ -19,7 +23,7 @@ pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes { &mut self, instance: Instance<'tcx>, function_source_hash: u64, - id: CounterValueReference, + index: CounterValueReference, region: CodeRegion, ) -> bool; @@ -33,7 +37,7 @@ pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes { op: Op, rhs: ExpressionOperandId, region: Option, - ); + ) -> bool; /// Returns true if the region was added to the coverage map; false if `-Z instrument-coverage` /// is not enabled (a coverage map is not being generated). diff --git a/compiler/rustc_mir/src/transform/coverage/counters.rs b/compiler/rustc_mir/src/transform/coverage/counters.rs index c31f401780e..a3ae3021524 100644 --- a/compiler/rustc_mir/src/transform/coverage/counters.rs +++ b/compiler/rustc_mir/src/transform/coverage/counters.rs @@ -1,7 +1,15 @@ +use super::Error; + use super::debug; +use super::graph; +use super::spans; -use debug::DebugCounters; +use debug::{DebugCounters, NESTED_INDENT}; +use graph::{BasicCoverageBlock, BcbBranch, CoverageGraph, TraverseCoverageGraphWithLoops}; +use spans::CoverageSpan; +use rustc_data_structures::graph::WithNumNodes; +use rustc_index::bit_set::BitSet; use rustc_middle::mir::coverage::*; /// Manages the counter and expression indexes/IDs to generate `CoverageKind` components for MIR @@ -29,7 +37,19 @@ impl CoverageCounters { self.debug_counters.enable(); } - pub fn make_counter(&mut self, debug_block_label_fn: F) -> CoverageKind + /// Makes `CoverageKind` `Counter`s and `Expressions` for the `BasicCoverageBlocks` directly or + /// indirectly associated with `CoverageSpans`, and returns additional `Expression`s + /// representing intermediate values. + pub fn make_bcb_counters( + &mut self, + basic_coverage_blocks: &mut CoverageGraph, + coverage_spans: &Vec, + ) -> Result, Error> { + let mut bcb_counters = BcbCounters::new(self, basic_coverage_blocks); + bcb_counters.make_bcb_counters(coverage_spans) + } + + fn make_counter(&mut self, debug_block_label_fn: F) -> CoverageKind where F: Fn() -> Option, { @@ -43,7 +63,7 @@ impl CoverageCounters { counter } - pub fn make_expression( + fn make_expression( &mut self, lhs: ExpressionOperandId, op: Op, @@ -61,6 +81,17 @@ impl CoverageCounters { expression } + pub fn make_identity_counter(&mut self, counter_operand: ExpressionOperandId) -> CoverageKind { + let some_debug_block_label = if self.debug_counters.is_enabled() { + self.debug_counters.some_block_label(counter_operand).cloned() + } else { + None + }; + self.make_expression(counter_operand, Op::Add, ExpressionOperandId::ZERO, || { + some_debug_block_label.clone() + }) + } + /// Counter IDs start from one and go up. fn next_counter(&mut self) -> CounterValueReference { assert!(self.next_counter_id < u32::MAX - self.num_expressions); @@ -79,3 +110,490 @@ impl CoverageCounters { InjectedExpressionId::from(next) } } + +/// Traverse the `CoverageGraph` and add either a `Counter` or `Expression` to every BCB, to be +/// injected with `CoverageSpan`s. `Expressions` have no runtime overhead, so if a viable expression +/// (adding or subtracting two other counters or expressions) can compute the same result as an +/// embedded counter, an `Expression` should be used. +struct BcbCounters<'a> { + coverage_counters: &'a mut CoverageCounters, + basic_coverage_blocks: &'a mut CoverageGraph, +} + +impl<'a> BcbCounters<'a> { + fn new( + coverage_counters: &'a mut CoverageCounters, + basic_coverage_blocks: &'a mut CoverageGraph, + ) -> Self { + Self { coverage_counters, basic_coverage_blocks } + } + + /// If two `CoverageGraph` branch from another `BasicCoverageBlock`, one of the branches + /// can be counted by `Expression` by subtracting the other branch from the branching + /// block. Otherwise, the `BasicCoverageBlock` executed the least should have the `Counter`. + /// One way to predict which branch executes the least is by considering loops. A loop is exited + /// at a branch, so the branch that jumps to a `BasicCoverageBlock` outside the loop is almost + /// always executed less than the branch that does not exit the loop. + /// + /// Returns any non-code-span expressions created to represent intermediate values (such as to + /// add two counters so the result can be subtracted from another counter), or an Error with + /// message for subsequent debugging. + fn make_bcb_counters( + &mut self, + coverage_spans: &Vec, + ) -> Result, Error> { + debug!("make_bcb_counters(): adding a counter or expression to each BasicCoverageBlock"); + let num_bcbs = self.basic_coverage_blocks.num_nodes(); + let mut collect_intermediate_expressions = Vec::with_capacity(num_bcbs); + + let mut bcbs_with_coverage = BitSet::new_empty(num_bcbs); + for covspan in coverage_spans { + bcbs_with_coverage.insert(covspan.bcb); + } + + // FIXME(richkadel): Add more comments to explain the logic here and in the rest of this + // function, and refactor this function to break it up into smaller functions that are + // easier to understand. + + let mut traversal = TraverseCoverageGraphWithLoops::new(&self.basic_coverage_blocks); + while let Some(bcb) = traversal.next(self.basic_coverage_blocks) { + if bcbs_with_coverage.contains(bcb) { + debug!("{:?} has at least one `CoverageSpan`. Get or make its counter", bcb); + let branching_counter_operand = + self.get_or_make_counter_operand(bcb, &mut collect_intermediate_expressions)?; + + if self.bcb_needs_branch_counters(bcb) { + self.make_branch_counters( + &mut traversal, + bcb, + branching_counter_operand, + &mut collect_intermediate_expressions, + )?; + } + } else { + debug!( + "{:?} does not have any `CoverageSpan`s. A counter will only be added if \ + and when a covered BCB has an expression dependency.", + bcb, + ); + } + } + + if traversal.is_complete() { + Ok(collect_intermediate_expressions) + } else { + Error::from_string(format!( + "`TraverseCoverageGraphWithLoops` missed some `BasicCoverageBlock`s: {:?}", + traversal.unvisited(), + )) + } + } + + fn make_branch_counters( + &mut self, + traversal: &mut TraverseCoverageGraphWithLoops, + branching_bcb: BasicCoverageBlock, + branching_counter_operand: ExpressionOperandId, + collect_intermediate_expressions: &mut Vec, + ) -> Result<(), Error> { + let branches = self.bcb_branches(branching_bcb); + debug!( + "{:?} has some branch(es) without counters:\n {}", + branching_bcb, + branches + .iter() + .map(|branch| { + format!("{:?}: {:?}", branch, branch.counter(&self.basic_coverage_blocks)) + }) + .collect::>() + .join("\n "), + ); + + let expression_branch = self.choose_preferred_expression_branch(traversal, &branches); + // Assign a Counter or Expression to each branch, plus additional + // `Expression`s, as needed, to sum up intermediate results. + let mut some_sumup_counter_operand = None; + for branch in branches { + if branch != expression_branch { + let branch_counter_operand = if branch.is_only_path_to_target() { + debug!( + " {:?} has only one incoming edge (from {:?}), so adding a \ + counter", + branch, branching_bcb + ); + self.get_or_make_counter_operand( + branch.target_bcb, + collect_intermediate_expressions, + )? + } else { + debug!(" {:?} has multiple incoming edges, so adding an edge counter", branch); + self.get_or_make_edge_counter_operand( + branching_bcb, + branch.target_bcb, + collect_intermediate_expressions, + )? + }; + if let Some(sumup_counter_operand) = + some_sumup_counter_operand.replace(branch_counter_operand) + { + let intermediate_expression = self.coverage_counters.make_expression( + branch_counter_operand, + Op::Add, + sumup_counter_operand, + || None, + ); + debug!( + " [new intermediate expression: {}]", + self.format_counter(&intermediate_expression) + ); + let intermediate_expression_operand = intermediate_expression.as_operand_id(); + collect_intermediate_expressions.push(intermediate_expression); + some_sumup_counter_operand.replace(intermediate_expression_operand); + } + } + } + let sumup_counter_operand = + some_sumup_counter_operand.expect("sumup_counter_operand should have a value"); + debug!( + "Making an expression for the selected expression_branch: {:?} \ + (expression_branch predecessors: {:?})", + expression_branch, + self.bcb_predecessors(expression_branch.target_bcb), + ); + let expression = self.coverage_counters.make_expression( + branching_counter_operand, + Op::Subtract, + sumup_counter_operand, + || Some(format!("{:?}", expression_branch)), + ); + debug!("{:?} gets an expression: {}", expression_branch, self.format_counter(&expression)); + let bcb = expression_branch.target_bcb; + if expression_branch.is_only_path_to_target() { + self.basic_coverage_blocks[bcb].set_counter(expression)?; + } else { + self.basic_coverage_blocks[bcb].set_edge_counter_from(branching_bcb, expression)?; + } + Ok(()) + } + + fn get_or_make_counter_operand( + &mut self, + bcb: BasicCoverageBlock, + collect_intermediate_expressions: &mut Vec, + ) -> Result { + self.recursive_get_or_make_counter_operand(bcb, collect_intermediate_expressions, 1) + } + + fn recursive_get_or_make_counter_operand( + &mut self, + bcb: BasicCoverageBlock, + collect_intermediate_expressions: &mut Vec, + debug_indent_level: usize, + ) -> Result { + Ok({ + if let Some(counter_kind) = self.basic_coverage_blocks[bcb].counter() { + debug!( + "{}{:?} already has a counter: {}", + NESTED_INDENT.repeat(debug_indent_level), + bcb, + self.format_counter(counter_kind), + ); + counter_kind.as_operand_id() + } else { + let one_path_to_target = self.bcb_has_one_path_to_target(bcb); + if one_path_to_target || self.bcb_predecessors(bcb).contains(&bcb) { + let counter_kind = + self.coverage_counters.make_counter(|| Some(format!("{:?}", bcb))); + if one_path_to_target { + debug!( + "{}{:?} gets a new counter: {}", + NESTED_INDENT.repeat(debug_indent_level), + bcb, + self.format_counter(&counter_kind), + ); + } else { + debug!( + "{}{:?} has itself as its own predecessor. It can't be part of its own \ + Expression sum, so it will get its own new counter: {}. (Note, the \ + compiled code will generate an infinite loop.)", + NESTED_INDENT.repeat(debug_indent_level), + bcb, + self.format_counter(&counter_kind), + ); + } + self.basic_coverage_blocks[bcb].set_counter(counter_kind)? + } else { + let mut predecessors = self.bcb_predecessors(bcb).clone().into_iter(); + debug!( + "{}{:?} has multiple incoming edges and will get an expression that sums \ + them up...", + NESTED_INDENT.repeat(debug_indent_level), + bcb, + ); + let first_edge_counter_operand = self + .recursive_get_or_make_edge_counter_operand( + predecessors.next().unwrap(), + bcb, + collect_intermediate_expressions, + debug_indent_level + 1, + )?; + let mut some_sumup_edge_counter_operand = None; + for predecessor in predecessors { + let edge_counter_operand = self + .recursive_get_or_make_edge_counter_operand( + predecessor, + bcb, + collect_intermediate_expressions, + debug_indent_level + 1, + )?; + if let Some(sumup_edge_counter_operand) = + some_sumup_edge_counter_operand.replace(edge_counter_operand) + { + let intermediate_expression = self.coverage_counters.make_expression( + sumup_edge_counter_operand, + Op::Add, + edge_counter_operand, + || None, + ); + debug!( + "{}new intermediate expression: {}", + NESTED_INDENT.repeat(debug_indent_level), + self.format_counter(&intermediate_expression) + ); + let intermediate_expression_operand = + intermediate_expression.as_operand_id(); + collect_intermediate_expressions.push(intermediate_expression); + some_sumup_edge_counter_operand + .replace(intermediate_expression_operand); + } + } + let counter_kind = self.coverage_counters.make_expression( + first_edge_counter_operand, + Op::Add, + some_sumup_edge_counter_operand.unwrap(), + || Some(format!("{:?}", bcb)), + ); + debug!( + "{}{:?} gets a new counter (sum of predecessor counters): {}", + NESTED_INDENT.repeat(debug_indent_level), + bcb, + self.format_counter(&counter_kind) + ); + self.basic_coverage_blocks[bcb].set_counter(counter_kind)? + } + } + }) + } + + fn get_or_make_edge_counter_operand( + &mut self, + from_bcb: BasicCoverageBlock, + to_bcb: BasicCoverageBlock, + collect_intermediate_expressions: &mut Vec, + ) -> Result { + self.recursive_get_or_make_edge_counter_operand( + from_bcb, + to_bcb, + collect_intermediate_expressions, + 1, + ) + } + + fn recursive_get_or_make_edge_counter_operand( + &mut self, + from_bcb: BasicCoverageBlock, + to_bcb: BasicCoverageBlock, + collect_intermediate_expressions: &mut Vec, + debug_indent_level: usize, + ) -> Result { + Ok({ + let successors = self.bcb_successors(from_bcb).iter(); + if successors.len() > 1 { + if let Some(counter_kind) = + self.basic_coverage_blocks[to_bcb].edge_counter_from(from_bcb) + { + debug!( + "{}Edge {:?}->{:?} already has a counter: {}", + NESTED_INDENT.repeat(debug_indent_level), + from_bcb, + to_bcb, + self.format_counter(counter_kind) + ); + counter_kind.as_operand_id() + } else { + let counter_kind = self + .coverage_counters + .make_counter(|| Some(format!("{:?}->{:?}", from_bcb, to_bcb))); + debug!( + "{}Edge {:?}->{:?} gets a new counter: {}", + NESTED_INDENT.repeat(debug_indent_level), + from_bcb, + to_bcb, + self.format_counter(&counter_kind) + ); + self.basic_coverage_blocks[to_bcb] + .set_edge_counter_from(from_bcb, counter_kind)? + } + } else { + self.recursive_get_or_make_counter_operand( + from_bcb, + collect_intermediate_expressions, + debug_indent_level + 1, + )? + } + }) + } + + /// Select a branch for the expression, either the recommended `reloop_branch`, or + /// if none was found, select any branch. + fn choose_preferred_expression_branch( + &self, + traversal: &TraverseCoverageGraphWithLoops, + branches: &Vec, + ) -> BcbBranch { + let branch_needs_a_counter = + |branch: &BcbBranch| branch.counter(&self.basic_coverage_blocks).is_none(); + + let some_reloop_branch = self.find_some_reloop_branch(traversal, &branches); + if let Some(reloop_branch_without_counter) = + some_reloop_branch.filter(branch_needs_a_counter) + { + debug!( + "Selecting reloop_branch={:?} that still needs a counter, to get the \ + `Expression`", + reloop_branch_without_counter + ); + reloop_branch_without_counter + } else { + let &branch_without_counter = branches + .iter() + .find(|&&branch| branch.counter(&self.basic_coverage_blocks).is_none()) + .expect( + "needs_branch_counters was `true` so there should be at least one \ + branch", + ); + debug!( + "Selecting any branch={:?} that still needs a counter, to get the \ + `Expression` because there was no `reloop_branch`, or it already had a \ + counter", + branch_without_counter + ); + branch_without_counter + } + } + + /// At most one of the branches (or its edge, from the branching_bcb, + /// if the branch has multiple incoming edges) can have a counter computed by + /// expression. + /// + /// If at least one of the branches leads outside of a loop (`found_loop_exit` is + /// true), and at least one other branch does not exit the loop (the first of which + /// is captured in `some_reloop_branch`), it's likely any reloop branch will be + /// executed far more often than loop exit branch, making the reloop branch a better + /// candidate for an expression. + fn find_some_reloop_branch( + &self, + traversal: &TraverseCoverageGraphWithLoops, + branches: &Vec, + ) -> Option { + let branch_needs_a_counter = + |branch: &BcbBranch| branch.counter(&self.basic_coverage_blocks).is_none(); + + let mut some_reloop_branch: Option = None; + for context in traversal.context_stack.iter().rev() { + if let Some((backedge_from_bcbs, _)) = &context.loop_backedges { + let mut found_loop_exit = false; + for &branch in branches.iter() { + if backedge_from_bcbs.iter().any(|&backedge_from_bcb| { + self.bcb_is_dominated_by(backedge_from_bcb, branch.target_bcb) + }) { + if let Some(reloop_branch) = some_reloop_branch { + if reloop_branch.counter(&self.basic_coverage_blocks).is_none() { + // we already found a candidate reloop_branch that still + // needs a counter + continue; + } + } + // The path from branch leads back to the top of the loop. Set this + // branch as the `reloop_branch`. If this branch already has a + // counter, and we find another reloop branch that doesn't have a + // counter yet, that branch will be selected as the `reloop_branch` + // instead. + some_reloop_branch = Some(branch); + } else { + // The path from branch leads outside this loop + found_loop_exit = true; + } + if found_loop_exit + && some_reloop_branch.filter(branch_needs_a_counter).is_some() + { + // Found both a branch that exits the loop and a branch that returns + // to the top of the loop (`reloop_branch`), and the `reloop_branch` + // doesn't already have a counter. + break; + } + } + if !found_loop_exit { + debug!( + "No branches exit the loop, so any branch without an existing \ + counter can have the `Expression`." + ); + break; + } + if some_reloop_branch.is_some() { + debug!( + "Found a branch that exits the loop and a branch the loops back to \ + the top of the loop (`reloop_branch`). The `reloop_branch` will \ + get the `Expression`, as long as it still needs a counter." + ); + break; + } + // else all branches exited this loop context, so run the same checks with + // the outer loop(s) + } + } + some_reloop_branch + } + + #[inline] + fn bcb_predecessors(&self, bcb: BasicCoverageBlock) -> &Vec { + &self.basic_coverage_blocks.predecessors[bcb] + } + + #[inline] + fn bcb_successors(&self, bcb: BasicCoverageBlock) -> &Vec { + &self.basic_coverage_blocks.successors[bcb] + } + + #[inline] + fn bcb_branches(&self, from_bcb: BasicCoverageBlock) -> Vec { + self.bcb_successors(from_bcb) + .iter() + .map(|&to_bcb| BcbBranch::from_to(from_bcb, to_bcb, &self.basic_coverage_blocks)) + .collect::>() + } + + fn bcb_needs_branch_counters(&self, bcb: BasicCoverageBlock) -> bool { + let branch_needs_a_counter = + |branch: &BcbBranch| branch.counter(&self.basic_coverage_blocks).is_none(); + let branches = self.bcb_branches(bcb); + branches.len() > 1 && branches.iter().any(branch_needs_a_counter) + } + + /// Returns true if the BasicCoverageBlock has zero or one incoming edge. (If zero, it should be + /// the entry point for the function.) + #[inline] + fn bcb_has_one_path_to_target(&self, bcb: BasicCoverageBlock) -> bool { + self.bcb_predecessors(bcb).len() <= 1 + } + + #[inline] + fn bcb_is_dominated_by(&self, node: BasicCoverageBlock, dom: BasicCoverageBlock) -> bool { + self.basic_coverage_blocks.is_dominated_by(node, dom) + } + + #[inline] + fn format_counter(&self, counter_kind: &CoverageKind) -> String { + self.coverage_counters.debug_counters.format_counter(counter_kind) + } +} diff --git a/compiler/rustc_mir/src/transform/coverage/debug.rs b/compiler/rustc_mir/src/transform/coverage/debug.rs index fbf2ad224a8..7080975aee5 100644 --- a/compiler/rustc_mir/src/transform/coverage/debug.rs +++ b/compiler/rustc_mir/src/transform/coverage/debug.rs @@ -13,6 +13,8 @@ use rustc_middle::ty::TyCtxt; use std::lazy::SyncOnceCell; +pub const NESTED_INDENT: &str = " "; + const RUSTC_COVERAGE_DEBUG_OPTIONS: &str = "RUSTC_COVERAGE_DEBUG_OPTIONS"; pub(crate) fn debug_options<'a>() -> &'a DebugOptions { @@ -24,20 +26,29 @@ pub(crate) fn debug_options<'a>() -> &'a DebugOptions { /// Parses and maintains coverage-specific debug options captured from the environment variable /// "RUSTC_COVERAGE_DEBUG_OPTIONS", if set. Options can be set on the command line by, for example: /// -/// $ RUSTC_COVERAGE_DEBUG_OPTIONS=counter-format=block cargo build +/// $ RUSTC_COVERAGE_DEBUG_OPTIONS=counter-format=block,allow_unused_expressions=n cargo build #[derive(Debug, Clone)] pub(crate) struct DebugOptions { + pub allow_unused_expressions: bool, counter_format: ExpressionFormat, } impl DebugOptions { fn new() -> Self { + let mut allow_unused_expressions = true; let mut counter_format = ExpressionFormat::default(); if let Ok(env_debug_options) = std::env::var(RUSTC_COVERAGE_DEBUG_OPTIONS) { for setting_str in env_debug_options.replace(" ", "").replace("-", "_").split(",") { let mut setting = setting_str.splitn(2, "="); match setting.next() { + Some(option) if option == "allow_unused_expressions" => { + allow_unused_expressions = bool_option_val(option, setting.next()); + debug!( + "{} env option `allow_unused_expressions` is set to {}", + RUSTC_COVERAGE_DEBUG_OPTIONS, allow_unused_expressions + ); + } Some(option) if option == "counter_format" => { if let Some(strval) = setting.next() { counter_format = counter_format_option_val(strval); @@ -66,7 +77,26 @@ impl DebugOptions { } } - Self { counter_format } + Self { allow_unused_expressions, counter_format } + } +} + +fn bool_option_val(option: &str, some_strval: Option<&str>) -> bool { + if let Some(val) = some_strval { + if vec!["yes", "y", "on", "true"].contains(&val) { + true + } else if vec!["no", "n", "off", "false"].contains(&val) { + false + } else { + bug!( + "Unsupported value `{}` for option `{}` in environment variable {}", + option, + val, + RUSTC_COVERAGE_DEBUG_OPTIONS + ) + } + } else { + true } } @@ -147,6 +177,14 @@ impl DebugCounters { } } + pub fn some_block_label(&self, operand: ExpressionOperandId) -> Option<&String> { + self.some_counters.as_ref().map_or(None, |counters| { + counters + .get(&operand) + .map_or(None, |debug_counter| debug_counter.some_block_label.as_ref()) + }) + } + pub fn format_counter(&self, counter_kind: &CoverageKind) -> String { match *counter_kind { CoverageKind::Counter { .. } => { @@ -242,16 +280,22 @@ impl DebugCounter { pub(crate) struct GraphvizData { some_bcb_to_coverage_spans_with_counters: Option>>, + some_bcb_to_dependency_counters: Option>>, some_edge_to_counter: Option>, } impl GraphvizData { pub fn new() -> Self { - Self { some_bcb_to_coverage_spans_with_counters: None, some_edge_to_counter: None } + Self { + some_bcb_to_coverage_spans_with_counters: None, + some_bcb_to_dependency_counters: None, + some_edge_to_counter: None, + } } pub fn enable(&mut self) { self.some_bcb_to_coverage_spans_with_counters = Some(FxHashMap::default()); + self.some_bcb_to_dependency_counters = Some(FxHashMap::default()); self.some_edge_to_counter = Some(FxHashMap::default()); } @@ -287,6 +331,187 @@ impl GraphvizData { None } } + + pub fn add_bcb_dependency_counter( + &mut self, + bcb: BasicCoverageBlock, + counter_kind: &CoverageKind, + ) { + if let Some(bcb_to_dependency_counters) = self.some_bcb_to_dependency_counters.as_mut() { + bcb_to_dependency_counters + .entry(bcb) + .or_insert_with(|| Vec::new()) + .push(counter_kind.clone()); + } + } + + pub fn get_bcb_dependency_counters( + &self, + bcb: BasicCoverageBlock, + ) -> Option<&Vec> { + if let Some(bcb_to_dependency_counters) = self.some_bcb_to_dependency_counters.as_ref() { + bcb_to_dependency_counters.get(&bcb) + } else { + None + } + } + + pub fn set_edge_counter( + &mut self, + from_bcb: BasicCoverageBlock, + to_bb: BasicBlock, + counter_kind: &CoverageKind, + ) { + if let Some(edge_to_counter) = self.some_edge_to_counter.as_mut() { + edge_to_counter.insert((from_bcb, to_bb), counter_kind.clone()).expect_none( + "invalid attempt to insert more than one edge counter for the same edge", + ); + } + } + + pub fn get_edge_counter( + &self, + from_bcb: BasicCoverageBlock, + to_bb: BasicBlock, + ) -> Option<&CoverageKind> { + if let Some(edge_to_counter) = self.some_edge_to_counter.as_ref() { + edge_to_counter.get(&(from_bcb, to_bb)) + } else { + None + } + } +} + +/// If enabled, this struct captures additional data used to track whether expressions were used, +/// directly or indirectly, to compute the coverage counts for all `CoverageSpan`s, and any that are +/// _not_ used are retained in the `unused_expressions` Vec, to be included in debug output (logs +/// and/or a `CoverageGraph` graphviz output). +pub(crate) struct UsedExpressions { + some_used_expression_operands: + Option>>, + some_unused_expressions: + Option, BasicCoverageBlock)>>, +} + +impl UsedExpressions { + pub fn new() -> Self { + Self { some_used_expression_operands: None, some_unused_expressions: None } + } + + pub fn enable(&mut self) { + self.some_used_expression_operands = Some(FxHashMap::default()); + self.some_unused_expressions = Some(Vec::new()); + } + + pub fn is_enabled(&mut self) -> bool { + self.some_used_expression_operands.is_some() + } + + pub fn add_expression_operands(&mut self, expression: &CoverageKind) { + if let Some(used_expression_operands) = self.some_used_expression_operands.as_mut() { + if let CoverageKind::Expression { id, lhs, rhs, .. } = *expression { + used_expression_operands.entry(lhs).or_insert_with(|| Vec::new()).push(id); + used_expression_operands.entry(rhs).or_insert_with(|| Vec::new()).push(id); + } + } + } + + pub fn expression_is_used(&mut self, expression: &CoverageKind) -> bool { + if let Some(used_expression_operands) = self.some_used_expression_operands.as_ref() { + used_expression_operands.contains_key(&expression.as_operand_id()) + } else { + false + } + } + + pub fn add_unused_expression_if_not_found( + &mut self, + expression: &CoverageKind, + edge_from_bcb: Option, + target_bcb: BasicCoverageBlock, + ) { + if let Some(used_expression_operands) = self.some_used_expression_operands.as_ref() { + if !used_expression_operands.contains_key(&expression.as_operand_id()) { + self.some_unused_expressions.as_mut().unwrap().push(( + expression.clone(), + edge_from_bcb, + target_bcb, + )); + } + } + } + + /// Return the list of unused counters (if any) as a tuple with the counter (`CoverageKind`), + /// optional `from_bcb` (if it was an edge counter), and `target_bcb`. + pub fn get_unused_expressions( + &self, + ) -> Vec<(CoverageKind, Option, BasicCoverageBlock)> { + if let Some(unused_expressions) = self.some_unused_expressions.as_ref() { + unused_expressions.clone() + } else { + Vec::new() + } + } + + /// If enabled, validate that every BCB or edge counter not directly associated with a coverage + /// span is at least indirectly associated (it is a dependency of a BCB counter that _is_ + /// associated with a coverage span). + pub fn validate( + &mut self, + bcb_counters_without_direct_coverage_spans: &Vec<( + Option, + BasicCoverageBlock, + CoverageKind, + )>, + ) { + if self.is_enabled() { + let mut not_validated = bcb_counters_without_direct_coverage_spans + .iter() + .map(|(_, _, counter_kind)| counter_kind) + .collect::>(); + let mut validating_count = 0; + while not_validated.len() != validating_count { + let to_validate = not_validated.split_off(0); + validating_count = to_validate.len(); + for counter_kind in to_validate { + if self.expression_is_used(counter_kind) { + self.add_expression_operands(counter_kind); + } else { + not_validated.push(counter_kind); + } + } + } + } + } + + pub fn alert_on_unused_expressions(&self, debug_counters: &DebugCounters) { + if let Some(unused_expressions) = self.some_unused_expressions.as_ref() { + for (counter_kind, edge_from_bcb, target_bcb) in unused_expressions { + let unused_counter_message = if let Some(from_bcb) = edge_from_bcb.as_ref() { + format!( + "non-coverage edge counter found without a dependent expression, in \ + {:?}->{:?}; counter={}", + from_bcb, + target_bcb, + debug_counters.format_counter(&counter_kind), + ) + } else { + format!( + "non-coverage counter found without a dependent expression, in {:?}; \ + counter={}", + target_bcb, + debug_counters.format_counter(&counter_kind), + ) + }; + + if debug_options().allow_unused_expressions { + debug!("WARNING: {}", unused_counter_message); + } else { + bug!("{}", unused_counter_message); + } + } + } + } } /// Generates the MIR pass `CoverageSpan`-specific spanview dump file. @@ -337,6 +562,8 @@ pub(crate) fn dump_coverage_graphviz( basic_coverage_blocks: &CoverageGraph, debug_counters: &DebugCounters, graphviz_data: &GraphvizData, + intermediate_expressions: &Vec, + debug_used_expressions: &UsedExpressions, ) { let mir_source = mir_body.source; let def_id = mir_source.def_id(); @@ -347,21 +574,62 @@ pub(crate) fn dump_coverage_graphviz( debug_counters, &basic_coverage_blocks[bcb], graphviz_data.get_bcb_coverage_spans_with_counters(bcb), + graphviz_data.get_bcb_dependency_counters(bcb), + // intermediate_expressions are injected into the mir::START_BLOCK, so + // include them in the first BCB. + if bcb.index() == 0 { Some(&intermediate_expressions) } else { None }, ) }; let edge_labels = |from_bcb| { let from_bcb_data = &basic_coverage_blocks[from_bcb]; let from_terminator = from_bcb_data.terminator(mir_body); - from_terminator - .kind - .fmt_successor_labels() + let mut edge_labels = from_terminator.kind.fmt_successor_labels(); + edge_labels.retain(|label| label.to_string() != "unreachable"); + let edge_counters = from_terminator + .successors() + .map(|&successor_bb| graphviz_data.get_edge_counter(from_bcb, successor_bb)); + edge_labels .iter() - .map(|label| label.to_string()) + .zip(edge_counters) + .map(|(label, some_counter)| { + if let Some(counter) = some_counter { + format!("{}\n{}", label, debug_counters.format_counter(counter)) + } else { + label.to_string() + } + }) .collect::>() }; let graphviz_name = format!("Cov_{}_{}", def_id.krate.index(), def_id.index.index()); - let graphviz_writer = + let mut graphviz_writer = GraphvizWriter::new(basic_coverage_blocks, &graphviz_name, node_content, edge_labels); + let unused_expressions = debug_used_expressions.get_unused_expressions(); + if unused_expressions.len() > 0 { + graphviz_writer.set_graph_label(&format!( + "Unused expressions:\n {}", + unused_expressions + .as_slice() + .iter() + .map(|(counter_kind, edge_from_bcb, target_bcb)| { + if let Some(from_bcb) = edge_from_bcb.as_ref() { + format!( + "{:?}->{:?}: {}", + from_bcb, + target_bcb, + debug_counters.format_counter(&counter_kind), + ) + } else { + format!( + "{:?}: {}", + target_bcb, + debug_counters.format_counter(&counter_kind), + ) + } + }) + .collect::>() + .join("\n ") + )); + } let mut file = pretty::create_dump_file(tcx, "dot", None, pass_name, &0, mir_source) .expect("Unexpected error creating BasicCoverageBlock graphviz DOT file"); graphviz_writer @@ -375,9 +643,22 @@ fn bcb_to_string_sections( debug_counters: &DebugCounters, bcb_data: &BasicCoverageBlockData, some_coverage_spans_with_counters: Option<&Vec<(CoverageSpan, CoverageKind)>>, + some_dependency_counters: Option<&Vec>, + some_intermediate_expressions: Option<&Vec>, ) -> Vec { let len = bcb_data.basic_blocks.len(); let mut sections = Vec::new(); + if let Some(collect_intermediate_expressions) = some_intermediate_expressions { + sections.push( + collect_intermediate_expressions + .iter() + .map(|expression| { + format!("Intermediate {}", debug_counters.format_counter(expression)) + }) + .collect::>() + .join("\n"), + ); + } if let Some(coverage_spans_with_counters) = some_coverage_spans_with_counters { sections.push( coverage_spans_with_counters @@ -393,6 +674,19 @@ fn bcb_to_string_sections( .join("\n"), ); } + if let Some(dependency_counters) = some_dependency_counters { + sections.push(format!( + "Non-coverage counters:\n {}", + dependency_counters + .iter() + .map(|counter| debug_counters.format_counter(counter)) + .collect::>() + .join(" \n"), + )); + } + if let Some(counter_kind) = &bcb_data.counter_kind { + sections.push(format!("{:?}", counter_kind)); + } let non_term_blocks = bcb_data.basic_blocks[0..len - 1] .iter() .map(|&bb| format!("{:?}: {}", bb, term_type(&mir_body[bb].terminator().kind))) diff --git a/compiler/rustc_mir/src/transform/coverage/graph.rs b/compiler/rustc_mir/src/transform/coverage/graph.rs index 3d3e76f907b..84062541701 100644 --- a/compiler/rustc_mir/src/transform/coverage/graph.rs +++ b/compiler/rustc_mir/src/transform/coverage/graph.rs @@ -1,7 +1,11 @@ +use super::Error; + +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::graph::dominators::{self, Dominators}; -use rustc_data_structures::graph::{self, GraphSuccessors, WithNumNodes}; +use rustc_data_structures::graph::{self, GraphSuccessors, WithNumNodes, WithStartNode}; use rustc_index::bit_set::BitSet; use rustc_index::vec::IndexVec; +use rustc_middle::mir::coverage::*; use rustc_middle::mir::{self, BasicBlock, BasicBlockData, Terminator, TerminatorKind}; use std::ops::{Index, IndexMut}; @@ -183,6 +187,13 @@ impl CoverageGraph { self.bcbs.iter_enumerated() } + #[inline(always)] + pub fn iter_enumerated_mut( + &mut self, + ) -> impl Iterator { + self.bcbs.iter_enumerated_mut() + } + #[inline(always)] pub fn bcb_from_bb(&self, bb: BasicBlock) -> Option { if bb.index() < self.bb_to_bcb.len() { self.bb_to_bcb[bb] } else { None } @@ -293,12 +304,14 @@ rustc_index::newtype_index! { #[derive(Debug, Clone)] pub(crate) struct BasicCoverageBlockData { pub basic_blocks: Vec, + pub counter_kind: Option, + edge_from_bcbs: Option>, } impl BasicCoverageBlockData { pub fn from(basic_blocks: Vec) -> Self { assert!(basic_blocks.len() > 0); - Self { basic_blocks } + Self { basic_blocks, counter_kind: None, edge_from_bcbs: None } } #[inline(always)] @@ -316,6 +329,91 @@ impl BasicCoverageBlockData { &mir_body[self.last_bb()].terminator() } + #[inline(always)] + pub fn set_counter( + &mut self, + counter_kind: CoverageKind, + ) -> Result { + debug_assert!( + // If the BCB has an edge counter (to be injected into a new `BasicBlock`), it can also + // have an expression (to be injected into an existing `BasicBlock` represented by this + // `BasicCoverageBlock`). + self.edge_from_bcbs.is_none() || counter_kind.is_expression(), + "attempt to add a `Counter` to a BCB target with existing incoming edge counters" + ); + let operand = counter_kind.as_operand_id(); + let expect_none = self.counter_kind.replace(counter_kind); + if expect_none.is_some() { + return Error::from_string(format!( + "attempt to set a BasicCoverageBlock coverage counter more than once; \ + {:?} already had counter {:?}", + self, + expect_none.unwrap(), + )); + } + Ok(operand) + } + + #[inline(always)] + pub fn counter(&self) -> Option<&CoverageKind> { + self.counter_kind.as_ref() + } + + #[inline(always)] + pub fn take_counter(&mut self) -> Option { + self.counter_kind.take() + } + + #[inline(always)] + pub fn set_edge_counter_from( + &mut self, + from_bcb: BasicCoverageBlock, + counter_kind: CoverageKind, + ) -> Result { + if level_enabled!(tracing::Level::DEBUG) { + // If the BCB has an edge counter (to be injected into a new `BasicBlock`), it can also + // have an expression (to be injected into an existing `BasicBlock` represented by this + // `BasicCoverageBlock`). + if !self.counter_kind.as_ref().map_or(true, |c| c.is_expression()) { + return Error::from_string(format!( + "attempt to add an incoming edge counter from {:?} when the target BCB already \ + has a `Counter`", + from_bcb + )); + } + } + let operand = counter_kind.as_operand_id(); + let expect_none = self + .edge_from_bcbs + .get_or_insert_with(|| FxHashMap::default()) + .insert(from_bcb, counter_kind); + if expect_none.is_some() { + return Error::from_string(format!( + "attempt to set an edge counter more than once; from_bcb: \ + {:?} already had counter {:?}", + from_bcb, + expect_none.unwrap(), + )); + } + Ok(operand) + } + + #[inline(always)] + pub fn edge_counter_from(&self, from_bcb: BasicCoverageBlock) -> Option<&CoverageKind> { + if let Some(edge_from_bcbs) = &self.edge_from_bcbs { + edge_from_bcbs.get(&from_bcb) + } else { + None + } + } + + #[inline(always)] + pub fn take_edge_counters( + &mut self, + ) -> Option> { + self.edge_from_bcbs.take().map_or(None, |m| Some(m.into_iter())) + } + pub fn id(&self) -> String { format!( "@{}", @@ -328,6 +426,56 @@ impl BasicCoverageBlockData { } } +/// Represents a successor from a branching BasicCoverageBlock (such as the arms of a `SwitchInt`) +/// as either the successor BCB itself, if it has only one incoming edge, or the successor _plus_ +/// the specific branching BCB, representing the edge between the two. The latter case +/// distinguishes this incoming edge from other incoming edges to the same `target_bcb`. +#[derive(Clone, Copy, PartialEq, Eq)] +pub(crate) struct BcbBranch { + pub edge_from_bcb: Option, + pub target_bcb: BasicCoverageBlock, +} + +impl BcbBranch { + pub fn from_to( + from_bcb: BasicCoverageBlock, + to_bcb: BasicCoverageBlock, + basic_coverage_blocks: &CoverageGraph, + ) -> Self { + let edge_from_bcb = if basic_coverage_blocks.predecessors[to_bcb].len() > 1 { + Some(from_bcb) + } else { + None + }; + Self { edge_from_bcb, target_bcb: to_bcb } + } + + pub fn counter<'a>( + &self, + basic_coverage_blocks: &'a CoverageGraph, + ) -> Option<&'a CoverageKind> { + if let Some(from_bcb) = self.edge_from_bcb { + basic_coverage_blocks[self.target_bcb].edge_counter_from(from_bcb) + } else { + basic_coverage_blocks[self.target_bcb].counter() + } + } + + pub fn is_only_path_to_target(&self) -> bool { + self.edge_from_bcb.is_none() + } +} + +impl std::fmt::Debug for BcbBranch { + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if let Some(from_bcb) = self.edge_from_bcb { + write!(fmt, "{:?}->{:?}", from_bcb, self.target_bcb) + } else { + write!(fmt, "{:?}", self.target_bcb) + } + } +} + fn bcb_filtered_successors<'a, 'tcx>( body: &'tcx &'a mir::Body<'tcx>, term_kind: &'tcx TerminatorKind<'tcx>, @@ -344,6 +492,175 @@ fn bcb_filtered_successors<'a, 'tcx>( .filter(move |&&successor| body[successor].terminator().kind != TerminatorKind::Unreachable) } +/// Maintains separate worklists for each loop in the BasicCoverageBlock CFG, plus one for the +/// CoverageGraph outside all loops. This supports traversing the BCB CFG in a way that +/// ensures a loop is completely traversed before processing Blocks after the end of the loop. +#[derive(Debug)] +pub(crate) struct TraversalContext { + /// From one or more backedges returning to a loop header. + pub loop_backedges: Option<(Vec, BasicCoverageBlock)>, + + /// worklist, to be traversed, of CoverageGraph in the loop with the given loop + /// backedges, such that the loop is the inner inner-most loop containing these + /// CoverageGraph + pub worklist: Vec, +} + +pub(crate) struct TraverseCoverageGraphWithLoops { + pub backedges: IndexVec>, + pub context_stack: Vec, + visited: BitSet, +} + +impl TraverseCoverageGraphWithLoops { + pub fn new(basic_coverage_blocks: &CoverageGraph) -> Self { + let start_bcb = basic_coverage_blocks.start_node(); + let backedges = find_loop_backedges(basic_coverage_blocks); + let mut context_stack = Vec::new(); + context_stack.push(TraversalContext { loop_backedges: None, worklist: vec![start_bcb] }); + // `context_stack` starts with a `TraversalContext` for the main function context (beginning + // with the `start` BasicCoverageBlock of the function). New worklists are pushed to the top + // of the stack as loops are entered, and popped off of the stack when a loop's worklist is + // exhausted. + let visited = BitSet::new_empty(basic_coverage_blocks.num_nodes()); + Self { backedges, context_stack, visited } + } + + pub fn next(&mut self, basic_coverage_blocks: &CoverageGraph) -> Option { + debug!( + "TraverseCoverageGraphWithLoops::next - context_stack: {:?}", + self.context_stack.iter().rev().collect::>() + ); + while let Some(next_bcb) = { + // Strip contexts with empty worklists from the top of the stack + while self.context_stack.last().map_or(false, |context| context.worklist.is_empty()) { + self.context_stack.pop(); + } + // Pop the next bcb off of the current context_stack. If none, all BCBs were visited. + self.context_stack.last_mut().map_or(None, |context| context.worklist.pop()) + } { + if !self.visited.insert(next_bcb) { + debug!("Already visited: {:?}", next_bcb); + continue; + } + debug!("Visiting {:?}", next_bcb); + if self.backedges[next_bcb].len() > 0 { + debug!("{:?} is a loop header! Start a new TraversalContext...", next_bcb); + self.context_stack.push(TraversalContext { + loop_backedges: Some((self.backedges[next_bcb].clone(), next_bcb)), + worklist: Vec::new(), + }); + } + self.extend_worklist(basic_coverage_blocks, next_bcb); + return Some(next_bcb); + } + None + } + + pub fn extend_worklist( + &mut self, + basic_coverage_blocks: &CoverageGraph, + bcb: BasicCoverageBlock, + ) { + let successors = &basic_coverage_blocks.successors[bcb]; + debug!("{:?} has {} successors:", bcb, successors.len()); + for &successor in successors { + if successor == bcb { + debug!( + "{:?} has itself as its own successor. (Note, the compiled code will \ + generate an infinite loop.)", + bcb + ); + // Don't re-add this successor to the worklist. We are already processing it. + break; + } + for context in self.context_stack.iter_mut().rev() { + // Add successors of the current BCB to the appropriate context. Successors that + // stay within a loop are added to the BCBs context worklist. Successors that + // exit the loop (they are not dominated by the loop header) must be reachable + // from other BCBs outside the loop, and they will be added to a different + // worklist. + // + // Branching blocks (with more than one successor) must be processed before + // blocks with only one successor, to prevent unnecessarily complicating + // `Expression`s by creating a Counter in a `BasicCoverageBlock` that the + // branching block would have given an `Expression` (or vice versa). + let (some_successor_to_add, some_loop_header) = + if let Some((_, loop_header)) = context.loop_backedges { + if basic_coverage_blocks.is_dominated_by(successor, loop_header) { + (Some(successor), Some(loop_header)) + } else { + (None, None) + } + } else { + (Some(successor), None) + }; + if let Some(successor_to_add) = some_successor_to_add { + if basic_coverage_blocks.successors[successor_to_add].len() > 1 { + debug!( + "{:?} successor is branching. Prioritize it at the beginning of \ + the {}", + successor_to_add, + if let Some(loop_header) = some_loop_header { + format!("worklist for the loop headed by {:?}", loop_header) + } else { + String::from("non-loop worklist") + }, + ); + context.worklist.insert(0, successor_to_add); + } else { + debug!( + "{:?} successor is non-branching. Defer it to the end of the {}", + successor_to_add, + if let Some(loop_header) = some_loop_header { + format!("worklist for the loop headed by {:?}", loop_header) + } else { + String::from("non-loop worklist") + }, + ); + context.worklist.push(successor_to_add); + } + break; + } + } + } + } + + pub fn is_complete(&self) -> bool { + self.visited.count() == self.visited.domain_size() + } + + pub fn unvisited(&self) -> Vec { + let mut unvisited_set: BitSet = + BitSet::new_filled(self.visited.domain_size()); + unvisited_set.subtract(&self.visited); + unvisited_set.iter().collect::>() + } +} + +fn find_loop_backedges( + basic_coverage_blocks: &CoverageGraph, +) -> IndexVec> { + let num_bcbs = basic_coverage_blocks.num_nodes(); + let mut backedges = IndexVec::from_elem_n(Vec::::new(), num_bcbs); + + // Identify loops by their backedges + for (bcb, _) in basic_coverage_blocks.iter_enumerated() { + for &successor in &basic_coverage_blocks.successors[bcb] { + if basic_coverage_blocks.is_dominated_by(bcb, successor) { + let loop_header = successor; + let backedge_from_bcb = bcb; + debug!( + "Found BCB backedge: {:?} -> loop_header: {:?}", + backedge_from_bcb, loop_header + ); + backedges[loop_header].push(backedge_from_bcb); + } + } + } + backedges +} + pub struct ShortCircuitPreorder< 'a, 'tcx, diff --git a/compiler/rustc_mir/src/transform/coverage/mod.rs b/compiler/rustc_mir/src/transform/coverage/mod.rs index d1d94092c9d..c84ccf19213 100644 --- a/compiler/rustc_mir/src/transform/coverage/mod.rs +++ b/compiler/rustc_mir/src/transform/coverage/mod.rs @@ -6,7 +6,7 @@ mod graph; mod spans; use counters::CoverageCounters; -use graph::CoverageGraph; +use graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph}; use spans::{CoverageSpan, CoverageSpans}; use crate::transform::MirPass; @@ -21,11 +21,26 @@ use rustc_middle::hir; use rustc_middle::hir::map::blocks::FnLikeNode; use rustc_middle::ich::StableHashingContext; use rustc_middle::mir::coverage::*; -use rustc_middle::mir::{self, BasicBlock, Coverage, Statement, StatementKind}; +use rustc_middle::mir::{ + self, BasicBlock, BasicBlockData, Coverage, SourceInfo, Statement, StatementKind, Terminator, + TerminatorKind, +}; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::DefId; use rustc_span::{CharPos, Pos, SourceFile, Span, Symbol}; +/// A simple error message wrapper for `coverage::Error`s. +#[derive(Debug)] +pub(crate) struct Error { + message: String, +} + +impl Error { + pub fn from_string(message: String) -> Result { + Err(Self { message }) + } +} + /// Inserts `StatementKind::Coverage` statements that either instrument the binary with injected /// counters, via intrinsic `llvm.instrprof.increment`, and/or inject metadata used during codegen /// to construct the coverage map. @@ -104,6 +119,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { debug!("instrumenting {:?}, span: {}", def_id, source_map.span_to_string(body_span)); let mut graphviz_data = debug::GraphvizData::new(); + let mut debug_used_expressions = debug::UsedExpressions::new(); let dump_graphviz = tcx.sess.opts.debugging_opts.dump_mir_graphviz; if dump_graphviz { @@ -111,6 +127,10 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { self.coverage_counters.enable_debug(); } + if dump_graphviz || level_enabled!(tracing::Level::DEBUG) { + debug_used_expressions.enable(); + } + //////////////////////////////////////////////////// // Compute `CoverageSpan`s from the `CoverageGraph`. let coverage_spans = CoverageSpans::generate_coverage_spans( @@ -129,7 +149,53 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { ); } - self.inject_coverage_span_counters(coverage_spans, &mut graphviz_data); + //////////////////////////////////////////////////// + // Create an optimized mix of `Counter`s and `Expression`s for the `CoverageGraph`. Ensure + // every `CoverageSpan` has a `Counter` or `Expression` assigned to its `BasicCoverageBlock` + // and all `Expression` dependencies (operands) are also generated, for any other + // `BasicCoverageBlock`s not already associated with a `CoverageSpan`. + // + // Intermediate expressions (used to compute other `Expression` values), which have no + // direct associate to any `BasicCoverageBlock`, are returned in the method `Result`. + let intermediate_expressions_or_error = self + .coverage_counters + .make_bcb_counters(&mut self.basic_coverage_blocks, &coverage_spans); + + let (result, intermediate_expressions) = match intermediate_expressions_or_error { + Ok(intermediate_expressions) => { + // If debugging, add any intermediate expressions (which are not associated with any + // BCB) to the `debug_used_expressions` map. + if debug_used_expressions.is_enabled() { + for intermediate_expression in &intermediate_expressions { + debug_used_expressions.add_expression_operands(intermediate_expression); + } + } + + //////////////////////////////////////////////////// + // Remove the counter or edge counter from of each `CoverageSpan`s associated + // `BasicCoverageBlock`, and inject a `Coverage` statement into the MIR. + self.inject_coverage_span_counters( + coverage_spans, + &mut graphviz_data, + &mut debug_used_expressions, + ); + + //////////////////////////////////////////////////// + // For any remaining `BasicCoverageBlock` counters (that were not associated with + // any `CoverageSpan`), inject `Coverage` statements (_without_ code region `Span`s) + // to ensure `BasicCoverageBlock` counters that other `Expression`s may depend on + // are in fact counted, even though they don't directly contribute to counting + // their own independent code region's coverage. + self.inject_indirect_counters(&mut graphviz_data, &mut debug_used_expressions); + + // Intermediate expressions will be injected as the final step, after generating + // debug output, if any. + //////////////////////////////////////////////////// + + (Ok(()), intermediate_expressions) + } + Err(e) => (Err(e), Vec::new()), + }; if graphviz_data.is_enabled() { // Even if there was an error, a partial CoverageGraph can still generate a useful @@ -141,19 +207,40 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { &self.basic_coverage_blocks, &self.coverage_counters.debug_counters, &graphviz_data, + &intermediate_expressions, + &debug_used_expressions, ); } + + if let Err(e) = result { + bug!("Error processing: {:?}: {:?}", self.mir_body.source.def_id(), e) + }; + + // Depending on current `debug_options()`, `alert_on_unused_expressions()` could panic, so + // this check is performed as late as possible, to allow other debug output (logs and dump + // files), which might be helpful in analyzing unused expressions, to still be generated. + debug_used_expressions.alert_on_unused_expressions(&self.coverage_counters.debug_counters); + + //////////////////////////////////////////////////// + // Finally, inject the intermediate expressions collected along the way. + for intermediate_expression in intermediate_expressions { + inject_intermediate_expression(self.mir_body, intermediate_expression); + } } /// Inject a counter for each `CoverageSpan`. There can be multiple `CoverageSpan`s for a given - /// BCB, but only one actual counter needs to be incremented per BCB. `bcb_counters` maps each + /// BCB, but only one actual counter needs to be incremented per BCB. `bb_counters` maps each /// `bcb` to its `Counter`, when injected. Subsequent `CoverageSpan`s for a BCB that already has /// a `Counter` will inject an `Expression` instead, and compute its value by adding `ZERO` to /// the BCB `Counter` value. + /// + /// If debugging, add every BCB `Expression` associated with a `CoverageSpan`s to the + /// `used_expression_operands` map. fn inject_coverage_span_counters( &mut self, coverage_spans: Vec, graphviz_data: &mut debug::GraphvizData, + debug_used_expressions: &mut debug::UsedExpressions, ) { let tcx = self.tcx; let source_map = tcx.sess.source_map(); @@ -165,40 +252,194 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { for covspan in coverage_spans { let bcb = covspan.bcb; let span = covspan.span; - if let Some(&counter_operand) = bcb_counters[bcb].as_ref() { - let expression = self.coverage_counters.make_expression( - counter_operand, - Op::Add, - ExpressionOperandId::ZERO, - || Some(format!("{:?}", bcb)), - ); - debug!( - "Injecting counter expression {:?} at: {:?}:\n{}\n==========", - expression, - span, - source_map.span_to_snippet(span).expect("Error getting source for span"), - ); - graphviz_data.add_bcb_coverage_span_with_counter(bcb, &covspan, &expression); - let bb = self.basic_coverage_blocks[bcb].leader_bb(); - let code_region = make_code_region(file_name, &source_file, span, body_span); - inject_statement(self.mir_body, expression, bb, Some(code_region)); + let counter_kind = if let Some(&counter_operand) = bcb_counters[bcb].as_ref() { + self.coverage_counters.make_identity_counter(counter_operand) + } else if let Some(counter_kind) = self.bcb_data_mut(bcb).take_counter() { + bcb_counters[bcb] = Some(counter_kind.as_operand_id()); + debug_used_expressions.add_expression_operands(&counter_kind); + counter_kind } else { - let counter = self.coverage_counters.make_counter(|| Some(format!("{:?}", bcb))); - debug!( - "Injecting counter {:?} at: {:?}:\n{}\n==========", - counter, - span, - source_map.span_to_snippet(span).expect("Error getting source for span"), - ); - let counter_operand = counter.as_operand_id(); - bcb_counters[bcb] = Some(counter_operand); - graphviz_data.add_bcb_coverage_span_with_counter(bcb, &covspan, &counter); - let bb = self.basic_coverage_blocks[bcb].leader_bb(); - let code_region = make_code_region(file_name, &source_file, span, body_span); - inject_statement(self.mir_body, counter, bb, Some(code_region)); + bug!("Every BasicCoverageBlock should have a Counter or Expression"); + }; + graphviz_data.add_bcb_coverage_span_with_counter(bcb, &covspan, &counter_kind); + let some_code_region = if self.is_code_region_redundant(bcb, span, body_span) { + None + } else { + Some(make_code_region(file_name, &source_file, span, body_span)) + }; + inject_statement(self.mir_body, counter_kind, self.bcb_last_bb(bcb), some_code_region); + } + } + + /// Returns true if the type of `BasicCoverageBlock` (specifically, it's `BasicBlock`s + /// `TerminatorKind`) with the given `Span` (relative to the `body_span`) is known to produce + /// a redundant coverage count. + /// + /// There is at least one case for this, and if it's not handled, the last line in a function + /// will be double-counted. + /// + /// If this method returns `true`, the counter (which other `Expressions` may depend on) is + /// still injected, but without an associated code region. + fn is_code_region_redundant( + &self, + bcb: BasicCoverageBlock, + span: Span, + body_span: Span, + ) -> bool { + if span.hi() == body_span.hi() { + // All functions execute a `Return`-terminated `BasicBlock`, regardless of how the + // function returns; but only some functions also _can_ return after a `Goto` block + // that ends on the closing brace of the function (with the `Return`). When this + // happens, the last character is counted 2 (or possibly more) times, when we know + // the function returned only once (of course). By giving all `Goto` terminators at + // the end of a function a `non-reportable` code region, they are still counted + // if appropriate, but they don't increment the line counter, as long as their is + // also a `Return` on that last line. + if let TerminatorKind::Goto { .. } = self.bcb_terminator(bcb).kind { + return true; } } + false } + + /// `inject_coverage_span_counters()` looped through the `CoverageSpan`s and injected the + /// counter from the `CoverageSpan`s `BasicCoverageBlock`, removing it from the BCB in the + /// process (via `take_counter()`). + /// + /// Any other counter associated with a `BasicCoverageBlock`, or its incoming edge, but not + /// associated with a `CoverageSpan`, should only exist if the counter is a `Expression` + /// dependency (one of the expression operands). Collect them, and inject the additional + /// counters into the MIR, without a reportable coverage span. + fn inject_indirect_counters( + &mut self, + graphviz_data: &mut debug::GraphvizData, + debug_used_expressions: &mut debug::UsedExpressions, + ) { + let mut bcb_counters_without_direct_coverage_spans = Vec::new(); + for (target_bcb, target_bcb_data) in self.basic_coverage_blocks.iter_enumerated_mut() { + if let Some(counter_kind) = target_bcb_data.take_counter() { + bcb_counters_without_direct_coverage_spans.push((None, target_bcb, counter_kind)); + } + if let Some(edge_counters) = target_bcb_data.take_edge_counters() { + for (from_bcb, counter_kind) in edge_counters { + bcb_counters_without_direct_coverage_spans.push(( + Some(from_bcb), + target_bcb, + counter_kind, + )); + } + } + } + + // If debug is enabled, validate that every BCB or edge counter not directly associated + // with a coverage span is at least indirectly associated (it is a dependency of a BCB + // counter that _is_ associated with a coverage span). + debug_used_expressions.validate(&bcb_counters_without_direct_coverage_spans); + + for (edge_from_bcb, target_bcb, counter_kind) in bcb_counters_without_direct_coverage_spans + { + debug_used_expressions.add_unused_expression_if_not_found( + &counter_kind, + edge_from_bcb, + target_bcb, + ); + + match counter_kind { + CoverageKind::Counter { .. } => { + let inject_to_bb = if let Some(from_bcb) = edge_from_bcb { + // The MIR edge starts `from_bb` (the outgoing / last BasicBlock in + // `from_bcb`) and ends at `to_bb` (the incoming / first BasicBlock in the + // `target_bcb`; also called the `leader_bb`). + let from_bb = self.bcb_last_bb(from_bcb); + let to_bb = self.bcb_leader_bb(target_bcb); + + let new_bb = inject_edge_counter_basic_block(self.mir_body, from_bb, to_bb); + graphviz_data.set_edge_counter(from_bcb, new_bb, &counter_kind); + debug!( + "Edge {:?} (last {:?}) -> {:?} (leader {:?}) requires a new MIR \ + BasicBlock {:?}, for unclaimed edge counter {}", + edge_from_bcb, + from_bb, + target_bcb, + to_bb, + new_bb, + self.format_counter(&counter_kind), + ); + new_bb + } else { + let target_bb = self.bcb_last_bb(target_bcb); + graphviz_data.add_bcb_dependency_counter(target_bcb, &counter_kind); + debug!( + "{:?} ({:?}) gets a new Coverage statement for unclaimed counter {}", + target_bcb, + target_bb, + self.format_counter(&counter_kind), + ); + target_bb + }; + + inject_statement(self.mir_body, counter_kind, inject_to_bb, None); + } + CoverageKind::Expression { .. } => { + inject_intermediate_expression(self.mir_body, counter_kind) + } + _ => bug!("CoverageKind should be a counter"), + } + } + } + + #[inline] + fn bcb_leader_bb(&self, bcb: BasicCoverageBlock) -> BasicBlock { + self.bcb_data(bcb).leader_bb() + } + + #[inline] + fn bcb_last_bb(&self, bcb: BasicCoverageBlock) -> BasicBlock { + self.bcb_data(bcb).last_bb() + } + + #[inline] + fn bcb_terminator(&self, bcb: BasicCoverageBlock) -> &Terminator<'tcx> { + self.bcb_data(bcb).terminator(self.mir_body) + } + + #[inline] + fn bcb_data(&self, bcb: BasicCoverageBlock) -> &BasicCoverageBlockData { + &self.basic_coverage_blocks[bcb] + } + + #[inline] + fn bcb_data_mut(&mut self, bcb: BasicCoverageBlock) -> &mut BasicCoverageBlockData { + &mut self.basic_coverage_blocks[bcb] + } + + #[inline] + fn format_counter(&self, counter_kind: &CoverageKind) -> String { + self.coverage_counters.debug_counters.format_counter(counter_kind) + } +} + +fn inject_edge_counter_basic_block( + mir_body: &mut mir::Body<'tcx>, + from_bb: BasicBlock, + to_bb: BasicBlock, +) -> BasicBlock { + let span = mir_body[from_bb].terminator().source_info.span.shrink_to_hi(); + let new_bb = mir_body.basic_blocks_mut().push(BasicBlockData { + statements: vec![], // counter will be injected here + terminator: Some(Terminator { + source_info: SourceInfo::outermost(span), + kind: TerminatorKind::Goto { target: to_bb }, + }), + is_cleanup: false, + }); + let edge_ref = mir_body[from_bb] + .terminator_mut() + .successors_mut() + .find(|successor| **successor == to_bb) + .expect("from_bb should have a successor for to_bb"); + *edge_ref = new_bb; + new_bb } fn inject_statement( @@ -223,6 +464,20 @@ fn inject_statement( data.statements.push(statement); } +// Non-code expressions are injected into the coverage map, without generating executable code. +fn inject_intermediate_expression(mir_body: &mut mir::Body<'tcx>, expression: CoverageKind) { + debug_assert!(if let CoverageKind::Expression { .. } = expression { true } else { false }); + debug!(" injecting non-code expression {:?}", expression); + let inject_in_bb = mir::START_BLOCK; + let data = &mut mir_body[inject_in_bb]; + let source_info = data.terminator().source_info; + let statement = Statement { + source_info, + kind: StatementKind::Coverage(box Coverage { kind: expression, code_region: None }), + }; + data.statements.push(statement); +} + /// Convert the Span into its file name, start line and column, and end line and column fn make_code_region( file_name: Symbol, diff --git a/src/test/mir-opt/coverage_graphviz.bar.InstrumentCoverage.0.dot b/src/test/mir-opt/coverage_graphviz.bar.InstrumentCoverage.0.dot index df9f7aa627b..efc06bdea57 100644 --- a/src/test/mir-opt/coverage_graphviz.bar.InstrumentCoverage.0.dot +++ b/src/test/mir-opt/coverage_graphviz.bar.InstrumentCoverage.0.dot @@ -2,5 +2,5 @@ digraph Cov_0_4 { graph [fontname="Courier, monospace"]; node [fontname="Courier, monospace"]; edge [fontname="Courier, monospace"]; - bcb0__Cov_0_4 [shape="none", label=<
bcb0
Counter(bcb0) at 19:5-20:2
19:5-19:9: @0[0]: _0 = const true
20:2-20:2: @0.Return: return
bb0: Return
>]; + bcb0__Cov_0_4 [shape="none", label=<
bcb0
Counter(bcb0) at 19:5-20:2
19:5-19:9: @0[0]: _0 = const true
20:2-20:2: @0.Return: return
bb0: Return
>]; } diff --git a/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot b/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot index 051ef498fb7..5ddd112fe62 100644 --- a/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot +++ b/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot @@ -2,9 +2,9 @@ digraph Cov_0_3 { graph [fontname="Courier, monospace"]; node [fontname="Courier, monospace"]; edge [fontname="Courier, monospace"]; - bcb2__Cov_0_3 [shape="none", label=<
bcb2
Counter(bcb2) at 14:6-14:6
14:6-14:6: @4.Goto: goto -> bb0
bb4: Goto
>]; + bcb2__Cov_0_3 [shape="none", label=<
bcb2
Expression(bcb0 - bcb1) at 14:6-14:6
14:6-14:6: @4.Goto: goto -> bb0
bb4: Goto
>]; bcb1__Cov_0_3 [shape="none", label=<
bcb1
Counter(bcb1) at 12:13-12:18
12:13-12:18: @5[0]: _0 = const ()
Expression(bcb1 + 0) at 15:2-15:2
15:2-15:2: @5.Return: return
bb3: FalseEdge
bb5: Return
>]; - bcb0__Cov_0_3 [shape="none", label=<
bcb0
Counter(bcb0) at 11:12-11:17
11:12-11:17: @1.Call: _2 = bar() -> [return: bb2, unwind: bb6]
11:12-11:17: @2[0]: FakeRead(ForMatchedPlace, _2)
bb0: FalseUnwind
bb1: Call
bb2: SwitchInt
>]; + bcb0__Cov_0_3 [shape="none", label=<
bcb0
Counter(bcb0) at 11:12-11:17
11:12-11:17: @1.Call: _2 = bar() -> [return: bb2, unwind: bb6]
11:12-11:17: @2[0]: FakeRead(ForMatchedPlace, _2)
bb0: FalseUnwind
bb1: Call
bb2: SwitchInt
>]; bcb2__Cov_0_3 -> bcb0__Cov_0_3 [label=<>]; bcb0__Cov_0_3 -> bcb2__Cov_0_3 [label=]; bcb0__Cov_0_3 -> bcb1__Cov_0_3 [label=]; diff --git a/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff b/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff index ddc65085e80..c67d0e2ffe6 100644 --- a/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff +++ b/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff @@ -8,7 +8,6 @@ let mut _3: !; // in scope 0 at /the/src/instrument_coverage.rs:12:18: 14:10 bb0: { -+ Coverage::Counter(1) for /the/src/instrument_coverage.rs:12:12 - 12:17; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 falseUnwind -> [real: bb1, cleanup: bb6]; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 } @@ -22,25 +21,26 @@ bb2: { FakeRead(ForMatchedPlace, _2); // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17 ++ Coverage::Counter(1) for /the/src/instrument_coverage.rs:12:12 - 12:17; // scope 0 at /the/src/instrument_coverage.rs:12:9: 14:10 switchInt(_2) -> [false: bb4, otherwise: bb3]; // scope 0 at /the/src/instrument_coverage.rs:12:9: 14:10 } bb3: { -+ Coverage::Counter(2) for /the/src/instrument_coverage.rs:13:13 - 13:18; // scope 0 at /the/src/instrument_coverage.rs:12:9: 14:10 -+ Coverage::Expression(4294967295) = 2 + 0 for /the/src/instrument_coverage.rs:16:1 - 16:2; // scope 0 at /the/src/instrument_coverage.rs:12:9: 14:10 falseEdge -> [real: bb5, imaginary: bb4]; // scope 0 at /the/src/instrument_coverage.rs:12:9: 14:10 } bb4: { _1 = const (); // scope 0 at /the/src/instrument_coverage.rs:12:9: 14:10 StorageDead(_2); // scope 0 at /the/src/instrument_coverage.rs:15:5: 15:6 -+ Coverage::Counter(3) for /the/src/instrument_coverage.rs:15:6 - 15:7; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 ++ Coverage::Expression(4294967295) = 1 - 2 for /the/src/instrument_coverage.rs:15:6 - 15:7; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 goto -> bb0; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 } bb5: { _0 = const (); // scope 0 at /the/src/instrument_coverage.rs:13:13: 13:18 StorageDead(_2); // scope 0 at /the/src/instrument_coverage.rs:15:5: 15:6 ++ Coverage::Counter(2) for /the/src/instrument_coverage.rs:13:13 - 13:18; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2 ++ Coverage::Expression(4294967294) = 2 + 0 for /the/src/instrument_coverage.rs:16:1 - 16:2; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2 return; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2 } diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.drop_trait.json b/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.drop_trait.json index 7a7e4c04f00..bd2e2d56d4a 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.drop_trait.json +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.drop_trait.json @@ -21,8 +21,8 @@ "percent": 100 }, "regions": { - "count": 6, - "covered": 6, + "count": 5, + "covered": 5, "notcovered": 0, "percent": 100 } @@ -46,8 +46,8 @@ "percent": 100 }, "regions": { - "count": 6, - "covered": 6, + "count": 5, + "covered": 5, "notcovered": 0, "percent": 100 } diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.generics.json b/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.generics.json index 1025cd3de80..a50f4657e20 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.generics.json +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.generics.json @@ -21,8 +21,8 @@ "percent": 100 }, "regions": { - "count": 7, - "covered": 7, + "count": 6, + "covered": 6, "notcovered": 0, "percent": 100 } @@ -46,8 +46,8 @@ "percent": 100 }, "regions": { - "count": 7, - "covered": 7, + "count": 6, + "covered": 6, "notcovered": 0, "percent": 100 } diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.if_else.json b/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.if_else.json index 2d2ad1dbe3f..36f81ceae19 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.if_else.json +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.if_else.json @@ -16,15 +16,15 @@ "percent": 100 }, "lines": { - "count": 29, - "covered": 21, - "percent": 72.41379310344827 + "count": 28, + "covered": 19, + "percent": 67.85714285714286 }, "regions": { - "count": 9, - "covered": 7, + "count": 7, + "covered": 5, "notcovered": 2, - "percent": 77.77777777777779 + "percent": 71.42857142857143 } } } @@ -41,15 +41,15 @@ "percent": 100 }, "lines": { - "count": 29, - "covered": 21, - "percent": 72.41379310344827 + "count": 28, + "covered": 19, + "percent": 67.85714285714286 }, "regions": { - "count": 9, - "covered": 7, + "count": 7, + "covered": 5, "notcovered": 2, - "percent": 77.77777777777779 + "percent": 71.42857142857143 } } } diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.try_error_result.json b/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.try_error_result.json index 39e17359eee..929e769b50a 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.try_error_result.json +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.try_error_result.json @@ -21,10 +21,10 @@ "percent": 94.73684210526315 }, "regions": { - "count": 18, - "covered": 15, + "count": 17, + "covered": 14, "notcovered": 3, - "percent": 83.33333333333334 + "percent": 82.35294117647058 } } } @@ -46,10 +46,10 @@ "percent": 94.73684210526315 }, "regions": { - "count": 18, - "covered": 15, + "count": 17, + "covered": 14, "notcovered": 3, - "percent": 83.33333333333334 + "percent": 82.35294117647058 } } } diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.various_conditions.json b/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.various_conditions.json index 464bb614ea1..d93458b6143 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.various_conditions.json +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.various_conditions.json @@ -21,10 +21,10 @@ "percent": 46.93877551020408 }, "regions": { - "count": 70, - "covered": 19, + "count": 69, + "covered": 18, "notcovered": 51, - "percent": 27.142857142857142 + "percent": 26.08695652173913 } } } @@ -46,10 +46,10 @@ "percent": 46.93877551020408 }, "regions": { - "count": 70, - "covered": 19, + "count": 69, + "covered": 18, "notcovered": 51, - "percent": 27.142857142857142 + "percent": 26.08695652173913 } } } diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.while_early_return.json b/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.while_early_return.json index a116a91a60a..a9e01604ccd 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.while_early_return.json +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_export_coverage.while_early_return.json @@ -21,10 +21,10 @@ "percent": 88.23529411764706 }, "regions": { - "count": 10, - "covered": 8, + "count": 9, + "covered": 7, "notcovered": 2, - "percent": 80 + "percent": 77.77777777777779 } } } @@ -46,10 +46,10 @@ "percent": 88.23529411764706 }, "regions": { - "count": 10, - "covered": 8, + "count": 9, + "covered": 7, "notcovered": 2, - "percent": 80 + "percent": 77.77777777777779 } } } diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.drop_trait.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.drop_trait.txt index 43592df1059..72aa020ca16 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.drop_trait.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.drop_trait.txt @@ -24,7 +24,7 @@ 24| | let _ = Firework { strength: 1000 }; 25| | 26| | Ok(()) - 27| 2|} + 27| 1|} 28| | 29| |// Expected program output: 30| |// Exiting with error... diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.generics.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.generics.txt index 11dc0aa65e2..86199d74763 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.generics.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.generics.txt @@ -57,7 +57,7 @@ 35| | let _ = Firework { strength: 1000 }; 36| | 37| | Ok(()) - 38| 2|} + 38| 1|} 39| | 40| |// Expected program output: 41| |// Exiting with error... diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.if_else.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.if_else.txt index 64cbc262521..5f899723e25 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.if_else.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.if_else.txt @@ -20,7 +20,7 @@ 20| 0| countdown 21| 0| = 22| 0| 100 - 23| 1| } + 23| | } 24| | 25| | if 26| 1| is_true @@ -36,6 +36,6 @@ 36| 0| = 37| 0| 100 38| 0| ; - 39| 1| } + 39| 0| } 40| 1|} diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.try_error_result.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.try_error_result.txt index c43b492db60..94c63c9a2b9 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.try_error_result.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.try_error_result.txt @@ -33,5 +33,5 @@ 32| 5| } 33| 5| } 34| 0| Ok(()) - 35| 2|} + 35| 1|} diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.various_conditions.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.various_conditions.txt index e0efe75043d..173ff4aa4c4 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.various_conditions.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.various_conditions.txt @@ -65,5 +65,5 @@ 64| | } else { 65| 0| return; 66| | }; - 67| 2|} + 67| 1|} diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.while_early_return.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.while_early_return.txt index e5c5b05a6fc..26041136d2f 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.while_early_return.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage.while_early_return.txt @@ -33,7 +33,7 @@ 33| | ; 34| | } 35| 0| Ok(()) - 36| 2|} + 36| 1|} 37| | 38| |// ISSUE(77553): Originally, this test had `Err(1)` on line 22 (instead of `Ok(())`) and 39| |// `std::process::exit(2)` on line 26 (instead of `Err(1)`); and this worked as expected on Linux diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.closure.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.closure.txt index 3eb07757c0d..ef43bbd78a6 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.closure.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.closure.txt @@ -2,8 +2,8 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/ Counter in file 0 20:21 -> 20:38, #1 Counter in file 0 21:20 -> 21:28, (#1 + 0) Counter in file 0 21:29 -> 23:18, #2 -Counter in file 0 23:18 -> 23:19, #3 -Counter in file 0 24:17 -> 25:14, #4 +Counter in file 0 23:18 -> 23:19, (#1 - #2) +Counter in file 0 24:17 -> 25:14, (#2 + (#1 - #2)) Counter in file 0 3:11 -> 18:13, #1 Counter in file 0 25:14 -> 33:9, (#1 + 0) Counter in file 0 40:6 -> 60:13, (#1 + 0) @@ -12,18 +12,18 @@ Counter in file 0 82:6 -> 93:2, (#1 + 0) Counter in file 0 77:13 -> 77:30, #1 Counter in file 0 78:12 -> 78:20, (#1 + 0) Counter in file 0 78:21 -> 80:10, #2 -Counter in file 0 80:10 -> 80:11, #3 -Counter in file 0 81:9 -> 82:6, #4 +Counter in file 0 80:10 -> 80:11, (#1 - #2) +Counter in file 0 81:9 -> 82:6, (#2 + (#1 - #2)) Counter in file 0 62:21 -> 62:38, #1 Counter in file 0 63:20 -> 63:28, (#1 + 0) Counter in file 0 63:29 -> 65:18, #2 -Counter in file 0 65:18 -> 65:19, #3 -Counter in file 0 66:17 -> 67:14, #4 +Counter in file 0 65:18 -> 65:19, (#1 - #2) +Counter in file 0 66:17 -> 67:14, (#2 + (#1 - #2)) Counter in file 0 35:13 -> 35:30, #1 Counter in file 0 36:12 -> 36:20, (#1 + 0) Counter in file 0 36:21 -> 38:10, #2 -Counter in file 0 38:10 -> 38:11, #3 -Counter in file 0 39:9 -> 40:6, #4 +Counter in file 0 38:10 -> 38:11, (#1 - #2) +Counter in file 0 39:9 -> 40:6, (#2 + (#1 - #2)) Emitting segments for file: ../coverage/closure.rs Combined regions: 3:11 -> 18:13 (count=1) diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.drop_trait.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.drop_trait.txt index 2bafe7d88e2..9716284f525 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.drop_trait.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.drop_trait.txt @@ -3,7 +3,7 @@ Counter in file 0 9:24 -> 11:6, #1 Counter in file 0 15:9 -> 17:42, #1 Counter in file 0 19:8 -> 19:12, (#1 + 0) Counter in file 0 20:9 -> 21:22, #2 -Counter in file 0 27:1 -> 27:2, #4 +Counter in file 0 27:1 -> 27:2, (#2 + 0) Emitting segments for file: ../coverage/drop_trait.rs Combined regions: 9:24 -> 11:6 (count=2) diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.generics.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.generics.txt index a13b1f3d786..5fbfe69b891 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.generics.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.generics.txt @@ -4,7 +4,7 @@ Counter in file 0 17:24 -> 19:6, #1 Counter in file 0 23:9 -> 28:28, #1 Counter in file 0 30:8 -> 30:12, (#1 + 0) Counter in file 0 31:9 -> 32:22, #2 -Counter in file 0 38:1 -> 38:2, #4 +Counter in file 0 38:1 -> 38:2, (#2 + 0) Counter in file 0 10:49 -> 12:6, #1 Counter in file 0 10:49 -> 12:6, #1 Emitting segments for file: ../coverage/generics.rs diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.if.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.if.txt index 2f063de5a39..48c9278a239 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.if.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.if.txt @@ -2,8 +2,8 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/ Counter in file 0 8:5 -> 18:10, #1 Counter in file 0 21:9 -> 21:16, (#1 + 0) Counter in file 0 22:5 -> 27:6, #2 -Counter in file 0 27:6 -> 27:7, #3 -Counter in file 0 28:1 -> 28:2, #4 +Counter in file 0 27:6 -> 27:7, (#1 - #2) +Counter in file 0 28:1 -> 28:2, (#2 + (#1 - #2)) Emitting segments for file: ../coverage/if.rs Combined regions: 8:5 -> 18:10 (count=1) diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.if_else.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.if_else.txt index 270a6f2b14a..1adf92300bf 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.if_else.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.if_else.txt @@ -1,11 +1,11 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/build/bin/llvm-cov show --debug --Xdemangler=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/stage0-tools-bin/rust-demangler --show-line-counts-or-regions --instr-profile=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-base/coverage-reports-base/if_else.profdata /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-base/coverage-reports-base/if_else Counter in file 0 7:9 -> 11:16, #1 Counter in file 0 12:5 -> 17:6, #2 -Counter in file 0 20:9 -> 22:16, #3 -Counter in file 0 26:9 -> 26:16, #4 -Counter in file 0 27:5 -> 32:6, #5 -Counter in file 0 34:5 -> 39:6, #6 -Counter in file 0 40:1 -> 40:2, #7 +Counter in file 0 20:9 -> 22:16, (#1 - #2) +Counter in file 0 26:9 -> 26:16, (#2 + (#1 - #2)) +Counter in file 0 27:5 -> 32:6, #3 +Counter in file 0 34:5 -> 39:6, ((#2 + (#1 - #2)) - #3) +Counter in file 0 40:1 -> 40:2, (#3 + ((#2 + (#1 - #2)) - #3)) Emitting segments for file: ../coverage/if_else.rs Combined regions: 7:9 -> 11:16 (count=1) diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.inner_items.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.inner_items.txt index fb863c73a63..0678be30dc3 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.inner_items.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.inner_items.txt @@ -6,11 +6,11 @@ Counter in file 0 21:9 -> 22:6, (#2 + 0) Counter in file 0 7:9 -> 9:26, #1 Counter in file 0 10:8 -> 10:15, (#1 + 0) Counter in file 0 10:16 -> 12:6, #2 -Counter in file 0 12:6 -> 12:7, #3 -Counter in file 0 48:8 -> 48:15, #4 -Counter in file 0 48:16 -> 50:6, #5 -Counter in file 0 50:6 -> 50:7, #6 -Counter in file 0 52:9 -> 57:2, #7 +Counter in file 0 12:6 -> 12:7, (#1 - #2) +Counter in file 0 48:8 -> 48:15, (#2 + (#1 - #2)) +Counter in file 0 48:16 -> 50:6, #3 +Counter in file 0 50:6 -> 50:7, ((#2 + (#1 - #2)) - #3) +Counter in file 0 52:9 -> 57:2, (#3 + ((#2 + (#1 - #2)) - #3)) Counter in file 0 33:42 -> 36:10, #1 Counter in file 0 41:37 -> 41:41, #1 Counter in file 0 42:13 -> 43:10, #2 diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.lazy_boolean.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.lazy_boolean.txt index 4561fcc5b36..e955fcd8ba0 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.lazy_boolean.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.lazy_boolean.txt @@ -2,40 +2,40 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/ Counter in file 0 7:9 -> 9:42, #1 Counter in file 0 10:8 -> 10:15, (#1 + 0) Counter in file 0 10:16 -> 14:6, #2 -Counter in file 0 14:6 -> 14:7, #3 -Counter in file 0 16:9 -> 16:17, #4 -Counter in file 0 18:13 -> 18:18, #5 -Counter in file 0 20:13 -> 20:18, #6 -Counter in file 0 20:18 -> 20:19, #7 -Counter in file 0 20:18 -> 20:19, #8 -Counter in file 0 23:9 -> 23:17, #9 -Counter in file 0 25:13 -> 25:18, (#4 + 0) -Counter in file 0 27:13 -> 27:18, #10 -Counter in file 0 27:18 -> 27:19, #11 -Counter in file 0 27:18 -> 27:19, #12 -Counter in file 0 29:9 -> 29:17, #13 -Counter in file 0 29:20 -> 29:25, (#9 + 0) -Counter in file 0 29:29 -> 29:34, #14 -Counter in file 0 29:34 -> 29:35, #15 -Counter in file 0 29:34 -> 29:35, #16 -Counter in file 0 30:9 -> 30:17, #17 -Counter in file 0 30:20 -> 30:25, (#13 + 0) -Counter in file 0 30:29 -> 30:34, #18 -Counter in file 0 30:34 -> 30:35, #19 -Counter in file 0 30:34 -> 30:35, #20 -Counter in file 0 33:9 -> 34:16, (#17 + 0) -Counter in file 0 35:5 -> 38:6, #21 -Counter in file 0 38:6 -> 38:7, #22 -Counter in file 0 41:9 -> 41:16, #23 -Counter in file 0 42:5 -> 45:6, #24 -Counter in file 0 47:5 -> 50:6, #25 -Counter in file 0 52:8 -> 52:16, #26 -Counter in file 0 52:17 -> 54:6, #27 -Counter in file 0 54:6 -> 54:7, #28 -Counter in file 0 56:8 -> 56:15, #29 -Counter in file 0 56:16 -> 58:6, #30 -Counter in file 0 58:12 -> 60:6, #31 -Counter in file 0 61:1 -> 61:2, #32 +Counter in file 0 14:6 -> 14:7, (#1 - #2) +Counter in file 0 16:9 -> 16:17, ((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) +Counter in file 0 18:13 -> 18:18, (#2 + (#1 - #2)) +Counter in file 0 20:13 -> 20:18, ((#2 + (#1 - #2)) - #3) +Counter in file 0 20:18 -> 20:19, (#3 + #4) +Counter in file 0 20:18 -> 20:19, (((#2 + (#1 - #2)) - #3) - #4) +Counter in file 0 23:9 -> 23:17, ((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) +Counter in file 0 25:13 -> 25:18, (((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) + 0) +Counter in file 0 27:13 -> 27:18, (((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) +Counter in file 0 27:18 -> 27:19, (#5 + #6) +Counter in file 0 27:18 -> 27:19, ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6) +Counter in file 0 29:9 -> 29:17, ((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) +Counter in file 0 29:20 -> 29:25, (((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) + 0) +Counter in file 0 29:29 -> 29:34, #7 +Counter in file 0 29:34 -> 29:35, ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8) +Counter in file 0 29:34 -> 29:35, (#7 - #8) +Counter in file 0 30:9 -> 30:17, ((#9 - #10) + ((((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) - #9) + #10)) +Counter in file 0 30:20 -> 30:25, (((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) + 0) +Counter in file 0 30:29 -> 30:34, #9 +Counter in file 0 30:34 -> 30:35, ((((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) - #9) + #10) +Counter in file 0 30:34 -> 30:35, (#9 - #10) +Counter in file 0 33:9 -> 34:16, (((#9 - #10) + ((((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) - #9) + #10)) + 0) +Counter in file 0 35:5 -> 38:6, #11 +Counter in file 0 38:6 -> 38:7, (((#9 - #10) + ((((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) - #9) + #10)) - #11) +Counter in file 0 41:9 -> 41:16, (#11 + (((#9 - #10) + ((((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) - #9) + #10)) - #11)) +Counter in file 0 42:5 -> 45:6, #12 +Counter in file 0 47:5 -> 50:6, ((#11 + (((#9 - #10) + ((((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) - #9) + #10)) - #11)) - #12) +Counter in file 0 52:8 -> 52:16, (#12 + ((#11 + (((#9 - #10) + ((((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) - #9) + #10)) - #11)) - #12)) +Counter in file 0 52:17 -> 54:6, #13 +Counter in file 0 54:6 -> 54:7, ((#12 + ((#11 + (((#9 - #10) + ((((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) - #9) + #10)) - #11)) - #12)) - #13) +Counter in file 0 56:8 -> 56:15, (#13 + ((#12 + ((#11 + (((#9 - #10) + ((((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) - #9) + #10)) - #11)) - #12)) - #13)) +Counter in file 0 56:16 -> 58:6, #14 +Counter in file 0 58:12 -> 60:6, ((#13 + ((#12 + ((#11 + (((#9 - #10) + ((((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) - #9) + #10)) - #11)) - #12)) - #13)) - #14) +Counter in file 0 61:1 -> 61:2, (#14 + ((#13 + ((#12 + ((#11 + (((#9 - #10) + ((((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) - #9) + #10)) - #11)) - #12)) - #13)) - #14)) Emitting segments for file: ../coverage/lazy_boolean.rs Combined regions: 7:9 -> 9:42 (count=1) diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.loops_and_branches.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.loops_and_branches.txt index 7cde2205cbf..171b77c9cc7 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.loops_and_branches.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.loops_and_branches.txt @@ -1,12 +1,12 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/build/bin/llvm-cov show --debug --Xdemangler=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/stage0-tools-bin/rust-demangler --show-line-counts-or-regions --instr-profile=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-base/coverage-reports-base/loops_and_branches.profdata /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-base/coverage-reports-base/loops_and_branches Counter in file 0 10:12 -> 10:16, #1 Counter in file 0 11:16 -> 11:21, #2 -Counter in file 0 14:14 -> 14:15, #6 -Counter in file 0 15:13 -> 15:31, #7 -Counter in file 0 15:31 -> 15:32, #8 -Counter in file 0 17:10 -> 17:11, #10 -Counter in file 0 18:9 -> 18:15, #11 -Counter in file 0 19:5 -> 19:6, #12 +Counter in file 0 14:14 -> 14:15, (#2 - #5) +Counter in file 0 15:13 -> 15:31, (0 + (#2 - #5)) +Counter in file 0 15:31 -> 15:32, #4 +Counter in file 0 17:10 -> 17:11, #3 +Counter in file 0 18:9 -> 18:15, (#3 + 0) +Counter in file 0 19:5 -> 19:6, (#4 + (#3 + 0)) Counter in file 0 22:11 -> 25:2, #1 Emitting segments for file: ../coverage/loops_and_branches.rs Combined regions: diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.nested_loops.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.nested_loops.txt index 59fb5c366f2..ac376c4f36a 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.nested_loops.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.nested_loops.txt @@ -1,22 +1,22 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/build/bin/llvm-cov show --debug --Xdemangler=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/stage0-tools-bin/rust-demangler --show-line-counts-or-regions --instr-profile=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-base/coverage-reports-base/nested_loops.profdata /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-base/coverage-reports-base/nested_loops Counter in file 0 2:9 -> 3:27, #1 -Counter in file 0 5:19 -> 5:32, #2 -Counter in file 0 6:13 -> 7:24, #3 -Counter in file 0 8:13 -> 8:14, #4 -Counter in file 0 8:18 -> 8:23, #5 -Counter in file 0 9:16 -> 9:22, (#4 + 0) -Counter in file 0 10:17 -> 10:22, #6 -Counter in file 0 12:13 -> 12:19, #7 -Counter in file 0 13:13 -> 13:19, #8 -Counter in file 0 14:16 -> 14:22, (#8 + 0) -Counter in file 0 15:17 -> 16:27, #9 -Counter in file 0 17:21 -> 17:33, #10 -Counter in file 0 19:21 -> 21:14, #11 -Counter in file 0 21:14 -> 21:15, #12 -Counter in file 0 22:10 -> 22:11, #13 -Counter in file 0 23:9 -> 23:23, #14 -Counter in file 0 24:6 -> 24:7, #15 -Counter in file 0 25:1 -> 25:2, #16 +Counter in file 0 5:19 -> 5:32, (#1 + #2) +Counter in file 0 6:13 -> 7:24, ((#1 + #2) - #3) +Counter in file 0 8:13 -> 8:14, ((((#1 + #2) - #3) + (#5 + #6)) - #7) +Counter in file 0 8:18 -> 8:23, (((#1 + #2) - #3) + (#5 + #6)) +Counter in file 0 9:16 -> 9:22, (((((#1 + #2) - #3) + (#5 + #6)) - #7) + 0) +Counter in file 0 10:17 -> 10:22, #8 +Counter in file 0 12:13 -> 12:19, #9 +Counter in file 0 13:13 -> 13:19, #10 +Counter in file 0 14:16 -> 14:22, (#10 + 0) +Counter in file 0 15:17 -> 16:27, #11 +Counter in file 0 17:21 -> 17:33, #4 +Counter in file 0 19:21 -> 21:14, #5 +Counter in file 0 21:14 -> 21:15, #6 +Counter in file 0 22:10 -> 22:11, (#5 + #6) +Counter in file 0 23:9 -> 23:23, #2 +Counter in file 0 24:6 -> 24:7, #3 +Counter in file 0 25:1 -> 25:2, (#4 + #3) Emitting segments for file: ../coverage/nested_loops.rs Combined regions: 2:9 -> 3:27 (count=1) diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.simple_loop.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.simple_loop.txt index d828e40ca3f..148768f423b 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.simple_loop.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.simple_loop.txt @@ -2,12 +2,12 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/ Counter in file 0 7:9 -> 9:26, #1 Counter in file 0 12:9 -> 12:16, (#1 + 0) Counter in file 0 13:5 -> 18:6, #2 -Counter in file 0 18:6 -> 18:7, #3 -Counter in file 0 23:13 -> 25:14, #4 -Counter in file 0 27:13 -> 27:18, #5 -Counter in file 0 30:9 -> 32:10, #6 -Counter in file 0 34:6 -> 34:7, #7 -Counter in file 0 35:1 -> 35:2, (#5 + 0) +Counter in file 0 18:6 -> 18:7, (#1 - #2) +Counter in file 0 23:13 -> 25:14, ((#2 + (#1 - #2)) + #3) +Counter in file 0 27:13 -> 27:18, #4 +Counter in file 0 30:9 -> 32:10, #3 +Counter in file 0 34:6 -> 34:7, (#2 + (#1 - #2)) +Counter in file 0 35:1 -> 35:2, (#4 + 0) Emitting segments for file: ../coverage/simple_loop.rs Combined regions: 7:9 -> 9:26 (count=1) diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.simple_match.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.simple_match.txt index e7932e0be04..2a3c004fa7a 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.simple_match.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.simple_match.txt @@ -2,18 +2,18 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/ Counter in file 0 7:9 -> 9:26, #1 Counter in file 0 10:8 -> 10:15, (#1 + 0) Counter in file 0 10:16 -> 12:6, #2 -Counter in file 0 12:6 -> 12:7, #3 -Counter in file 0 15:9 -> 15:10, #4 -Counter in file 0 17:9 -> 17:13, #5 -Counter in file 0 22:13 -> 22:22, (#4 + 0) -Counter in file 0 24:13 -> 24:14, #6 -Counter in file 0 26:17 -> 28:18, (#4 + 0) -Counter in file 0 28:18 -> 28:19, #7 -Counter in file 0 30:13 -> 37:14, (#6 + 0) -Counter in file 0 40:13 -> 40:15, #8 -Counter in file 0 42:6 -> 42:7, #9 -Counter in file 0 42:6 -> 42:7, #10 -Counter in file 0 43:1 -> 43:2, #11 +Counter in file 0 12:6 -> 12:7, (#1 - #2) +Counter in file 0 15:9 -> 15:10, (((#2 + (#1 - #2)) + (#3 + #4)) - #5) +Counter in file 0 17:9 -> 17:13, ((#2 + (#1 - #2)) + (#3 + #4)) +Counter in file 0 22:13 -> 22:22, ((((#2 + (#1 - #2)) + (#3 + #4)) - #5) + 0) +Counter in file 0 24:13 -> 24:14, #3 +Counter in file 0 26:17 -> 28:18, ((((#2 + (#1 - #2)) + (#3 + #4)) - #5) + 0) +Counter in file 0 28:18 -> 28:19, ((((#2 + (#1 - #2)) + (#3 + #4)) - #5) - #3) +Counter in file 0 30:13 -> 37:14, (#3 + 0) +Counter in file 0 40:13 -> 40:15, #4 +Counter in file 0 42:6 -> 42:7, (#2 + (#1 - #2)) +Counter in file 0 42:6 -> 42:7, (#3 + #4) +Counter in file 0 43:1 -> 43:2, #5 Emitting segments for file: ../coverage/simple_match.rs Combined regions: 7:9 -> 9:26 (count=1) diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.tight_infinite_loop.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.tight_infinite_loop.txt index a690874e3c0..5180ddd7de6 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.tight_infinite_loop.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.tight_infinite_loop.txt @@ -1,6 +1,6 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/build/bin/llvm-cov show --debug --Xdemangler=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/stage0-tools-bin/rust-demangler --show-line-counts-or-regions --instr-profile=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-base/coverage-reports-base/tight_infinite_loop.profdata /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-base/coverage-reports-base/tight_infinite_loop Counter in file 0 2:8 -> 2:13, #1 -Counter in file 0 5:1 -> 5:2, #4 +Counter in file 0 5:1 -> 5:2, (#1 - #2) Emitting segments for file: ../coverage/tight_infinite_loop.rs Combined regions: 2:8 -> 2:13 (count=1) diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.try_error_result.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.try_error_result.txt index 7dea637551d..30109a1e200 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.try_error_result.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.try_error_result.txt @@ -1,22 +1,21 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/build/bin/llvm-cov show --debug --Xdemangler=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/stage0-tools-bin/rust-demangler --show-line-counts-or-regions --instr-profile=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-base/coverage-reports-base/try_error_result.profdata /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-base/coverage-reports-base/try_error_result Counter in file 0 13:9 -> 14:23, #1 -Counter in file 0 17:9 -> 17:10, #2 -Counter in file 0 19:9 -> 19:14, #3 -Counter in file 0 21:9 -> 25:26, #4 -Counter in file 0 27:13 -> 27:41, #5 -Counter in file 0 27:41 -> 27:42, #6 -Counter in file 0 31:13 -> 31:42, #7 -Counter in file 0 31:42 -> 31:43, #8 -Counter in file 0 32:10 -> 32:11, #9 -Counter in file 0 32:10 -> 32:11, #10 -Counter in file 0 33:6 -> 33:7, #11 -Counter in file 0 34:5 -> 34:11, #12 -Counter in file 0 35:1 -> 35:2, #13 -Counter in file 0 35:1 -> 35:2, #14 +Counter in file 0 17:9 -> 17:10, ((#1 + (#2 + #3)) - #4) +Counter in file 0 19:9 -> 19:14, (#1 + (#2 + #3)) +Counter in file 0 21:9 -> 25:26, #7 +Counter in file 0 27:13 -> 27:41, #8 +Counter in file 0 27:41 -> 27:42, #5 +Counter in file 0 31:13 -> 31:42, (#7 - #8) +Counter in file 0 31:42 -> 31:43, #6 +Counter in file 0 32:10 -> 32:11, #2 +Counter in file 0 32:10 -> 32:11, #3 +Counter in file 0 33:6 -> 33:7, (#2 + #3) +Counter in file 0 34:5 -> 34:11, #4 +Counter in file 0 35:1 -> 35:2, ((#5 + #6) + #4) Counter in file 0 5:8 -> 5:20, #1 Counter in file 0 6:9 -> 6:16, #2 -Counter in file 0 8:9 -> 8:15, #3 -Counter in file 0 10:1 -> 10:2, #4 +Counter in file 0 8:9 -> 8:15, (#1 - #2) +Counter in file 0 10:1 -> 10:2, (#2 + (#1 - #2)) Emitting segments for file: ../coverage/try_error_result.rs Combined regions: 5:8 -> 5:20 (count=6) @@ -34,7 +33,7 @@ Combined regions: 32:10 -> 32:11 (count=5) 33:6 -> 33:7 (count=5) 34:5 -> 34:11 (count=0) - 35:1 -> 35:2 (count=2) + 35:1 -> 35:2 (count=1) Segment at 5:8 (count = 6), RegionEntry Segment at 5:20 (count = 0), Skipped Segment at 6:9 (count = 1), RegionEntry @@ -63,5 +62,5 @@ Segment at 33:6 (count = 5), RegionEntry Segment at 33:7 (count = 0), Skipped Segment at 34:5 (count = 0), RegionEntry Segment at 34:11 (count = 0), Skipped -Segment at 35:1 (count = 2), RegionEntry +Segment at 35:1 (count = 1), RegionEntry Segment at 35:2 (count = 0), Skipped diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.various_conditions.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.various_conditions.txt index 0fb135b2cc9..b229410a495 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.various_conditions.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.various_conditions.txt @@ -2,73 +2,72 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/ Counter in file 0 4:9 -> 4:26, #1 Counter in file 0 5:8 -> 5:12, (#1 + 0) Counter in file 0 5:13 -> 7:6, #2 -Counter in file 0 10:9 -> 10:10, #4 -Counter in file 0 10:16 -> 10:29, #5 -Counter in file 0 11:9 -> 12:10, #6 -Counter in file 0 13:15 -> 13:28, #7 -Counter in file 0 14:12 -> 14:25, #8 -Counter in file 0 14:29 -> 14:42, #9 -Counter in file 0 14:42 -> 14:43, #10 -Counter in file 0 14:42 -> 14:43, #11 -Counter in file 0 14:46 -> 14:60, #12 -Counter in file 0 14:60 -> 14:61, #13 -Counter in file 0 14:60 -> 14:61, #14 -Counter in file 0 14:61 -> 16:10, #15 -Counter in file 0 16:10 -> 16:11, #16 -Counter in file 0 17:9 -> 18:18, #17 -Counter in file 0 20:9 -> 20:15, #18 -Counter in file 0 23:9 -> 23:26, (#4 + 0) -Counter in file 0 24:8 -> 24:12, (#4 + 0) -Counter in file 0 24:13 -> 26:6, #19 -Counter in file 0 28:8 -> 28:21, #21 -Counter in file 0 29:9 -> 29:23, #22 -Counter in file 0 30:15 -> 30:28, #23 -Counter in file 0 31:12 -> 31:25, #24 -Counter in file 0 31:29 -> 31:42, #25 -Counter in file 0 31:42 -> 31:43, #26 -Counter in file 0 31:42 -> 31:43, #27 -Counter in file 0 31:46 -> 31:60, #28 -Counter in file 0 31:60 -> 31:61, #29 -Counter in file 0 31:60 -> 31:61, #30 -Counter in file 0 31:61 -> 33:10, #31 -Counter in file 0 33:10 -> 33:11, #32 -Counter in file 0 34:9 -> 34:23, #33 -Counter in file 0 36:9 -> 36:15, #34 -Counter in file 0 39:9 -> 39:26, #35 -Counter in file 0 40:8 -> 40:12, (#35 + 0) -Counter in file 0 40:13 -> 42:6, #36 -Counter in file 0 44:9 -> 44:10, #38 -Counter in file 0 44:16 -> 44:29, #39 -Counter in file 0 45:9 -> 45:23, #40 -Counter in file 0 46:15 -> 46:28, #41 -Counter in file 0 47:12 -> 47:25, #42 -Counter in file 0 47:29 -> 47:42, #43 -Counter in file 0 47:42 -> 47:43, #44 -Counter in file 0 47:42 -> 47:43, #45 -Counter in file 0 47:46 -> 47:60, #46 -Counter in file 0 47:60 -> 47:61, #47 -Counter in file 0 47:60 -> 47:61, #48 -Counter in file 0 47:61 -> 49:10, #49 -Counter in file 0 49:10 -> 49:11, #50 -Counter in file 0 50:9 -> 50:23, #51 -Counter in file 0 52:13 -> 54:15, #52 -Counter in file 0 57:9 -> 57:10, #53 -Counter in file 0 57:16 -> 57:29, (#38 + 0) -Counter in file 0 58:9 -> 58:23, #54 -Counter in file 0 59:15 -> 59:28, #55 -Counter in file 0 60:12 -> 60:25, #56 -Counter in file 0 60:29 -> 60:42, #57 -Counter in file 0 60:42 -> 60:43, #58 -Counter in file 0 60:42 -> 60:43, #59 -Counter in file 0 60:46 -> 60:60, #60 -Counter in file 0 60:60 -> 60:61, #61 -Counter in file 0 60:60 -> 60:61, #62 -Counter in file 0 60:61 -> 62:10, #63 -Counter in file 0 62:10 -> 62:11, #64 -Counter in file 0 63:9 -> 63:23, #65 -Counter in file 0 65:9 -> 65:15, #66 -Counter in file 0 67:1 -> 67:2, #67 -Counter in file 0 67:1 -> 67:2, #68 +Counter in file 0 10:9 -> 10:10, (#4 + #11) +Counter in file 0 10:16 -> 10:29, (#2 + 0) +Counter in file 0 11:9 -> 12:10, #4 +Counter in file 0 13:15 -> 13:28, ((#2 + 0) - #3) +Counter in file 0 14:12 -> 14:25, #5 +Counter in file 0 14:29 -> 14:42, (#5 - #13) +Counter in file 0 14:42 -> 14:43, (#13 + #14) +Counter in file 0 14:42 -> 14:43, ((#5 - #13) - #14) +Counter in file 0 14:46 -> 14:60, #21 +Counter in file 0 14:60 -> 14:61, (#17 + #18) +Counter in file 0 14:60 -> 14:61, (#21 - #18) +Counter in file 0 14:61 -> 16:10, #22 +Counter in file 0 16:10 -> 16:11, #23 +Counter in file 0 17:9 -> 18:18, #11 +Counter in file 0 20:9 -> 20:15, (((#2 + 0) - #3) - #5) +Counter in file 0 23:9 -> 23:26, ((#4 + #11) + 0) +Counter in file 0 24:8 -> 24:12, ((#4 + #11) + 0) +Counter in file 0 24:13 -> 26:6, #12 +Counter in file 0 28:8 -> 28:21, (#12 + 0) +Counter in file 0 29:9 -> 29:23, #16 +Counter in file 0 30:15 -> 30:28, ((#12 + 0) - #15) +Counter in file 0 31:12 -> 31:25, (((#12 + 0) - #15) - #8) +Counter in file 0 31:29 -> 31:42, ((((#12 + 0) - #15) - #8) - #24) +Counter in file 0 31:42 -> 31:43, (((((#12 + 0) - #15) - #8) - #24) - #25) +Counter in file 0 31:42 -> 31:43, (#24 + #25) +Counter in file 0 31:46 -> 31:60, #32 +Counter in file 0 31:60 -> 31:61, (#28 + #29) +Counter in file 0 31:60 -> 31:61, (#32 - #29) +Counter in file 0 31:61 -> 33:10, #33 +Counter in file 0 33:10 -> 33:11, #34 +Counter in file 0 34:9 -> 34:23, #19 +Counter in file 0 36:9 -> 36:15, #8 +Counter in file 0 39:9 -> 39:26, (#16 + #19) +Counter in file 0 40:8 -> 40:12, ((#16 + #19) + 0) +Counter in file 0 40:13 -> 42:6, #20 +Counter in file 0 44:9 -> 44:10, (#27 + #30) +Counter in file 0 44:16 -> 44:29, (#20 + 0) +Counter in file 0 45:9 -> 45:23, #27 +Counter in file 0 46:15 -> 46:28, ((#20 + 0) - #26) +Counter in file 0 47:12 -> 47:25, (((#20 + 0) - #26) - #7) +Counter in file 0 47:29 -> 47:42, ((((#20 + 0) - #26) - #7) - #35) +Counter in file 0 47:42 -> 47:43, (#35 + #36) +Counter in file 0 47:42 -> 47:43, (((((#20 + 0) - #26) - #7) - #35) - #36) +Counter in file 0 47:46 -> 47:60, #41 +Counter in file 0 47:60 -> 47:61, (#37 + #38) +Counter in file 0 47:60 -> 47:61, (#41 - #38) +Counter in file 0 47:61 -> 49:10, #42 +Counter in file 0 49:10 -> 49:11, #43 +Counter in file 0 50:9 -> 50:23, #30 +Counter in file 0 52:13 -> 54:15, #7 +Counter in file 0 57:9 -> 57:10, (#9 + #10) +Counter in file 0 57:16 -> 57:29, ((#27 + #30) + 0) +Counter in file 0 58:9 -> 58:23, #9 +Counter in file 0 59:15 -> 59:28, ((#27 + #30) - #31) +Counter in file 0 60:12 -> 60:25, (((#27 + #30) - #31) - #6) +Counter in file 0 60:29 -> 60:42, ((((#27 + #30) - #31) - #6) - #39) +Counter in file 0 60:42 -> 60:43, (#39 + #40) +Counter in file 0 60:42 -> 60:43, (((((#27 + #30) - #31) - #6) - #39) - #40) +Counter in file 0 60:46 -> 60:60, #46 +Counter in file 0 60:60 -> 60:61, (#46 - #45) +Counter in file 0 60:60 -> 60:61, (#44 + #45) +Counter in file 0 60:61 -> 62:10, #47 +Counter in file 0 62:10 -> 62:11, #48 +Counter in file 0 63:9 -> 63:23, #10 +Counter in file 0 65:9 -> 65:15, #6 +Counter in file 0 67:1 -> 67:2, ((#9 + #10) + (((#6 + #7) + #8) + (((#2 + 0) - #3) - #5))) Emitting segments for file: ../coverage/various_conditions.rs Combined regions: 4:9 -> 4:26 (count=1) @@ -131,7 +130,7 @@ Combined regions: 62:10 -> 62:11 (count=0) 63:9 -> 63:23 (count=0) 65:9 -> 65:15 (count=0) - 67:1 -> 67:2 (count=2) + 67:1 -> 67:2 (count=1) Segment at 4:9 (count = 1), RegionEntry Segment at 4:26 (count = 0), Skipped Segment at 5:8 (count = 1), RegionEntry @@ -236,5 +235,5 @@ Segment at 63:9 (count = 0), RegionEntry Segment at 63:23 (count = 0), Skipped Segment at 65:9 (count = 0), RegionEntry Segment at 65:15 (count = 0), Skipped -Segment at 67:1 (count = 2), RegionEntry +Segment at 67:1 (count = 1), RegionEntry Segment at 67:2 (count = 0), Skipped diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.while.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.while.txt index a2be958660e..d496805955f 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.while.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.while.txt @@ -1,8 +1,8 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/build/bin/llvm-cov show --debug --Xdemangler=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/stage0-tools-bin/rust-demangler --show-line-counts-or-regions --instr-profile=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-base/coverage-reports-base/while.profdata /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-base/coverage-reports-base/while Counter in file 0 2:9 -> 2:16, #1 -Counter in file 0 3:11 -> 3:20, #2 -Counter in file 0 3:21 -> 4:6, #3 -Counter in file 0 5:1 -> 5:2, #4 +Counter in file 0 3:11 -> 3:20, (#1 + #2) +Counter in file 0 3:21 -> 4:6, #2 +Counter in file 0 5:1 -> 5:2, ((#1 + #2) - #2) Emitting segments for file: ../coverage/while.rs Combined regions: 2:9 -> 2:16 (count=1) diff --git a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.while_early_return.txt b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.while_early_return.txt index 02ab24050ba..a343f5056ac 100644 --- a/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.while_early_return.txt +++ b/src/test/run-make-fulldeps/coverage-reports-base/expected_show_coverage_counters.while_early_return.txt @@ -1,14 +1,13 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/build/bin/llvm-cov show --debug --Xdemangler=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/stage0-tools-bin/rust-demangler --show-line-counts-or-regions --instr-profile=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-base/coverage-reports-base/while_early_return.profdata /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-base/coverage-reports-base/while_early_return Counter in file 0 5:9 -> 5:27, #1 -Counter in file 0 7:9 -> 9:10, #2 -Counter in file 0 12:13 -> 14:14, #3 -Counter in file 0 18:21 -> 20:22, #4 -Counter in file 0 22:21 -> 22:27, #5 -Counter in file 0 26:21 -> 26:27, #6 -Counter in file 0 30:9 -> 32:10, #7 -Counter in file 0 35:5 -> 35:11, #8 -Counter in file 0 36:1 -> 36:2, #9 -Counter in file 0 36:1 -> 36:2, #10 +Counter in file 0 7:9 -> 9:10, (#1 + #2) +Counter in file 0 12:13 -> 14:14, ((#1 + #2) - #3) +Counter in file 0 18:21 -> 20:22, #6 +Counter in file 0 22:21 -> 22:27, #4 +Counter in file 0 26:21 -> 26:27, #5 +Counter in file 0 30:9 -> 32:10, #2 +Counter in file 0 35:5 -> 35:11, #3 +Counter in file 0 36:1 -> 36:2, ((#4 + #5) + #3) Emitting segments for file: ../coverage/while_early_return.rs Combined regions: 5:9 -> 5:27 (count=1) @@ -19,7 +18,7 @@ Combined regions: 26:21 -> 26:27 (count=1) 30:9 -> 32:10 (count=6) 35:5 -> 35:11 (count=0) - 36:1 -> 36:2 (count=2) + 36:1 -> 36:2 (count=1) Segment at 5:9 (count = 1), RegionEntry Segment at 5:27 (count = 0), Skipped Segment at 7:9 (count = 7), RegionEntry @@ -36,5 +35,5 @@ Segment at 30:9 (count = 6), RegionEntry Segment at 32:10 (count = 0), Skipped Segment at 35:5 (count = 0), RegionEntry Segment at 35:11 (count = 0), Skipped -Segment at 36:1 (count = 2), RegionEntry +Segment at 36:1 (count = 1), RegionEntry Segment at 36:2 (count = 0), Skipped diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.drop_trait.json b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.drop_trait.json index 7a7e4c04f00..bd2e2d56d4a 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.drop_trait.json +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.drop_trait.json @@ -21,8 +21,8 @@ "percent": 100 }, "regions": { - "count": 6, - "covered": 6, + "count": 5, + "covered": 5, "notcovered": 0, "percent": 100 } @@ -46,8 +46,8 @@ "percent": 100 }, "regions": { - "count": 6, - "covered": 6, + "count": 5, + "covered": 5, "notcovered": 0, "percent": 100 } diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.generics.json b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.generics.json index 1025cd3de80..a50f4657e20 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.generics.json +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.generics.json @@ -21,8 +21,8 @@ "percent": 100 }, "regions": { - "count": 7, - "covered": 7, + "count": 6, + "covered": 6, "notcovered": 0, "percent": 100 } @@ -46,8 +46,8 @@ "percent": 100 }, "regions": { - "count": 7, - "covered": 7, + "count": 6, + "covered": 6, "notcovered": 0, "percent": 100 } diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.if_else.json b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.if_else.json index 2d2ad1dbe3f..36f81ceae19 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.if_else.json +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.if_else.json @@ -16,15 +16,15 @@ "percent": 100 }, "lines": { - "count": 29, - "covered": 21, - "percent": 72.41379310344827 + "count": 28, + "covered": 19, + "percent": 67.85714285714286 }, "regions": { - "count": 9, - "covered": 7, + "count": 7, + "covered": 5, "notcovered": 2, - "percent": 77.77777777777779 + "percent": 71.42857142857143 } } } @@ -41,15 +41,15 @@ "percent": 100 }, "lines": { - "count": 29, - "covered": 21, - "percent": 72.41379310344827 + "count": 28, + "covered": 19, + "percent": 67.85714285714286 }, "regions": { - "count": 9, - "covered": 7, + "count": 7, + "covered": 5, "notcovered": 2, - "percent": 77.77777777777779 + "percent": 71.42857142857143 } } } diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.try_error_result.json b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.try_error_result.json index 39e17359eee..929e769b50a 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.try_error_result.json +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.try_error_result.json @@ -21,10 +21,10 @@ "percent": 94.73684210526315 }, "regions": { - "count": 18, - "covered": 15, + "count": 17, + "covered": 14, "notcovered": 3, - "percent": 83.33333333333334 + "percent": 82.35294117647058 } } } @@ -46,10 +46,10 @@ "percent": 94.73684210526315 }, "regions": { - "count": 18, - "covered": 15, + "count": 17, + "covered": 14, "notcovered": 3, - "percent": 83.33333333333334 + "percent": 82.35294117647058 } } } diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.various_conditions.json b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.various_conditions.json index 464bb614ea1..d93458b6143 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.various_conditions.json +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.various_conditions.json @@ -21,10 +21,10 @@ "percent": 46.93877551020408 }, "regions": { - "count": 70, - "covered": 19, + "count": 69, + "covered": 18, "notcovered": 51, - "percent": 27.142857142857142 + "percent": 26.08695652173913 } } } @@ -46,10 +46,10 @@ "percent": 46.93877551020408 }, "regions": { - "count": 70, - "covered": 19, + "count": 69, + "covered": 18, "notcovered": 51, - "percent": 27.142857142857142 + "percent": 26.08695652173913 } } } diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.while_early_return.json b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.while_early_return.json index a116a91a60a..a9e01604ccd 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.while_early_return.json +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_export_coverage.while_early_return.json @@ -21,10 +21,10 @@ "percent": 88.23529411764706 }, "regions": { - "count": 10, - "covered": 8, + "count": 9, + "covered": 7, "notcovered": 2, - "percent": 80 + "percent": 77.77777777777779 } } } @@ -46,10 +46,10 @@ "percent": 88.23529411764706 }, "regions": { - "count": 10, - "covered": 8, + "count": 9, + "covered": 7, "notcovered": 2, - "percent": 80 + "percent": 77.77777777777779 } } } diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.drop_trait.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.drop_trait.txt index 43592df1059..72aa020ca16 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.drop_trait.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.drop_trait.txt @@ -24,7 +24,7 @@ 24| | let _ = Firework { strength: 1000 }; 25| | 26| | Ok(()) - 27| 2|} + 27| 1|} 28| | 29| |// Expected program output: 30| |// Exiting with error... diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.generics.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.generics.txt index 11dc0aa65e2..86199d74763 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.generics.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.generics.txt @@ -57,7 +57,7 @@ 35| | let _ = Firework { strength: 1000 }; 36| | 37| | Ok(()) - 38| 2|} + 38| 1|} 39| | 40| |// Expected program output: 41| |// Exiting with error... diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.if_else.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.if_else.txt index 64cbc262521..5f899723e25 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.if_else.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.if_else.txt @@ -20,7 +20,7 @@ 20| 0| countdown 21| 0| = 22| 0| 100 - 23| 1| } + 23| | } 24| | 25| | if 26| 1| is_true @@ -36,6 +36,6 @@ 36| 0| = 37| 0| 100 38| 0| ; - 39| 1| } + 39| 0| } 40| 1|} diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.try_error_result.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.try_error_result.txt index c43b492db60..94c63c9a2b9 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.try_error_result.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.try_error_result.txt @@ -33,5 +33,5 @@ 32| 5| } 33| 5| } 34| 0| Ok(()) - 35| 2|} + 35| 1|} diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.various_conditions.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.various_conditions.txt index e0efe75043d..173ff4aa4c4 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.various_conditions.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.various_conditions.txt @@ -65,5 +65,5 @@ 64| | } else { 65| 0| return; 66| | }; - 67| 2|} + 67| 1|} diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.while_early_return.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.while_early_return.txt index e5c5b05a6fc..26041136d2f 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.while_early_return.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage.while_early_return.txt @@ -33,7 +33,7 @@ 33| | ; 34| | } 35| 0| Ok(()) - 36| 2|} + 36| 1|} 37| | 38| |// ISSUE(77553): Originally, this test had `Err(1)` on line 22 (instead of `Ok(())`) and 39| |// `std::process::exit(2)` on line 26 (instead of `Err(1)`); and this worked as expected on Linux diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.closure.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.closure.txt index 39bf7bad9a1..d443ba0aba3 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.closure.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.closure.txt @@ -2,8 +2,8 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/ Counter in file 0 20:21 -> 20:38, #1 Counter in file 0 21:20 -> 21:28, (#1 + 0) Counter in file 0 21:29 -> 23:18, #2 -Counter in file 0 23:18 -> 23:19, #3 -Counter in file 0 24:17 -> 25:14, #4 +Counter in file 0 23:18 -> 23:19, (#1 - #2) +Counter in file 0 24:17 -> 25:14, (#2 + (#1 - #2)) Counter in file 0 3:11 -> 18:13, #1 Counter in file 0 25:14 -> 33:9, (#1 + 0) Counter in file 0 40:6 -> 60:13, (#1 + 0) @@ -12,18 +12,18 @@ Counter in file 0 82:6 -> 93:2, (#1 + 0) Counter in file 0 77:13 -> 77:30, #1 Counter in file 0 78:12 -> 78:20, (#1 + 0) Counter in file 0 78:21 -> 80:10, #2 -Counter in file 0 80:10 -> 80:11, #3 -Counter in file 0 81:9 -> 82:6, #4 +Counter in file 0 80:10 -> 80:11, (#1 - #2) +Counter in file 0 81:9 -> 82:6, (#2 + (#1 - #2)) Counter in file 0 62:21 -> 62:38, #1 Counter in file 0 63:20 -> 63:28, (#1 + 0) Counter in file 0 63:29 -> 65:18, #2 -Counter in file 0 65:18 -> 65:19, #3 -Counter in file 0 66:17 -> 67:14, #4 +Counter in file 0 65:18 -> 65:19, (#1 - #2) +Counter in file 0 66:17 -> 67:14, (#2 + (#1 - #2)) Counter in file 0 35:13 -> 35:30, #1 Counter in file 0 36:12 -> 36:20, (#1 + 0) Counter in file 0 36:21 -> 38:10, #2 -Counter in file 0 38:10 -> 38:11, #3 -Counter in file 0 39:9 -> 40:6, #4 +Counter in file 0 38:10 -> 38:11, (#1 - #2) +Counter in file 0 39:9 -> 40:6, (#2 + (#1 - #2)) Emitting segments for file: ../coverage/closure.rs Combined regions: 3:11 -> 18:13 (count=1) diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.drop_trait.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.drop_trait.txt index 124a01af342..08fbbd13adb 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.drop_trait.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.drop_trait.txt @@ -3,7 +3,7 @@ Counter in file 0 9:24 -> 11:6, #1 Counter in file 0 15:9 -> 17:42, #1 Counter in file 0 19:8 -> 19:12, (#1 + 0) Counter in file 0 20:9 -> 21:22, #2 -Counter in file 0 27:1 -> 27:2, #4 +Counter in file 0 27:1 -> 27:2, (#2 + 0) Emitting segments for file: ../coverage/drop_trait.rs Combined regions: 9:24 -> 11:6 (count=2) diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.generics.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.generics.txt index a0e9146035e..eb707c5e7ac 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.generics.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.generics.txt @@ -4,7 +4,7 @@ Counter in file 0 17:24 -> 19:6, #1 Counter in file 0 23:9 -> 28:28, #1 Counter in file 0 30:8 -> 30:12, (#1 + 0) Counter in file 0 31:9 -> 32:22, #2 -Counter in file 0 38:1 -> 38:2, #4 +Counter in file 0 38:1 -> 38:2, (#2 + 0) Counter in file 0 10:49 -> 12:6, #1 Counter in file 0 10:49 -> 12:6, #1 Emitting segments for file: ../coverage/generics.rs diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.if.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.if.txt index 325e6985e30..d186f440ddb 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.if.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.if.txt @@ -2,8 +2,8 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/ Counter in file 0 8:5 -> 18:10, #1 Counter in file 0 21:9 -> 21:16, (#1 + 0) Counter in file 0 22:5 -> 27:6, #2 -Counter in file 0 27:6 -> 27:7, #3 -Counter in file 0 28:1 -> 28:2, #4 +Counter in file 0 27:6 -> 27:7, (#1 - #2) +Counter in file 0 28:1 -> 28:2, (#2 + (#1 - #2)) Emitting segments for file: ../coverage/if.rs Combined regions: 8:5 -> 18:10 (count=1) diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.if_else.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.if_else.txt index 9406b6a269d..8220060f26f 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.if_else.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.if_else.txt @@ -1,11 +1,11 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/build/bin/llvm-cov show --debug --Xdemangler=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/stage0-tools-bin/rust-demangler --show-line-counts-or-regions --instr-profile=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-deadcode/coverage-reports-deadcode/if_else.profdata /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-deadcode/coverage-reports-deadcode/if_else Counter in file 0 7:9 -> 11:16, #1 Counter in file 0 12:5 -> 17:6, #2 -Counter in file 0 20:9 -> 22:16, #3 -Counter in file 0 26:9 -> 26:16, #4 -Counter in file 0 27:5 -> 32:6, #5 -Counter in file 0 34:5 -> 39:6, #6 -Counter in file 0 40:1 -> 40:2, #7 +Counter in file 0 20:9 -> 22:16, (#1 - #2) +Counter in file 0 26:9 -> 26:16, (#2 + (#1 - #2)) +Counter in file 0 27:5 -> 32:6, #3 +Counter in file 0 34:5 -> 39:6, ((#2 + (#1 - #2)) - #3) +Counter in file 0 40:1 -> 40:2, (#3 + ((#2 + (#1 - #2)) - #3)) Emitting segments for file: ../coverage/if_else.rs Combined regions: 7:9 -> 11:16 (count=1) diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.inner_items.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.inner_items.txt index ea6db9452a7..c173cc20f81 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.inner_items.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.inner_items.txt @@ -6,11 +6,11 @@ Counter in file 0 21:9 -> 22:6, (#2 + 0) Counter in file 0 7:9 -> 9:26, #1 Counter in file 0 10:8 -> 10:15, (#1 + 0) Counter in file 0 10:16 -> 12:6, #2 -Counter in file 0 12:6 -> 12:7, #3 -Counter in file 0 48:8 -> 48:15, #4 -Counter in file 0 48:16 -> 50:6, #5 -Counter in file 0 50:6 -> 50:7, #6 -Counter in file 0 52:9 -> 57:2, #7 +Counter in file 0 12:6 -> 12:7, (#1 - #2) +Counter in file 0 48:8 -> 48:15, (#2 + (#1 - #2)) +Counter in file 0 48:16 -> 50:6, #3 +Counter in file 0 50:6 -> 50:7, ((#2 + (#1 - #2)) - #3) +Counter in file 0 52:9 -> 57:2, (#3 + ((#2 + (#1 - #2)) - #3)) Counter in file 0 33:42 -> 36:10, #1 Counter in file 0 41:37 -> 41:41, #1 Counter in file 0 42:13 -> 43:10, #2 diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.lazy_boolean.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.lazy_boolean.txt index c95275c6223..191a3a58355 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.lazy_boolean.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.lazy_boolean.txt @@ -2,40 +2,40 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/ Counter in file 0 7:9 -> 9:42, #1 Counter in file 0 10:8 -> 10:15, (#1 + 0) Counter in file 0 10:16 -> 14:6, #2 -Counter in file 0 14:6 -> 14:7, #3 -Counter in file 0 16:9 -> 16:17, #4 -Counter in file 0 18:13 -> 18:18, #5 -Counter in file 0 20:13 -> 20:18, #6 -Counter in file 0 20:18 -> 20:19, #7 -Counter in file 0 20:18 -> 20:19, #8 -Counter in file 0 23:9 -> 23:17, #9 -Counter in file 0 25:13 -> 25:18, (#4 + 0) -Counter in file 0 27:13 -> 27:18, #10 -Counter in file 0 27:18 -> 27:19, #11 -Counter in file 0 27:18 -> 27:19, #12 -Counter in file 0 29:9 -> 29:17, #13 -Counter in file 0 29:20 -> 29:25, (#9 + 0) -Counter in file 0 29:29 -> 29:34, #14 -Counter in file 0 29:34 -> 29:35, #15 -Counter in file 0 29:34 -> 29:35, #16 -Counter in file 0 30:9 -> 30:17, #17 -Counter in file 0 30:20 -> 30:25, (#13 + 0) -Counter in file 0 30:29 -> 30:34, #18 -Counter in file 0 30:34 -> 30:35, #19 -Counter in file 0 30:34 -> 30:35, #20 -Counter in file 0 33:9 -> 34:16, (#17 + 0) -Counter in file 0 35:5 -> 38:6, #21 -Counter in file 0 38:6 -> 38:7, #22 -Counter in file 0 41:9 -> 41:16, #23 -Counter in file 0 42:5 -> 45:6, #24 -Counter in file 0 47:5 -> 50:6, #25 -Counter in file 0 52:8 -> 52:16, #26 -Counter in file 0 52:17 -> 54:6, #27 -Counter in file 0 54:6 -> 54:7, #28 -Counter in file 0 56:8 -> 56:15, #29 -Counter in file 0 56:16 -> 58:6, #30 -Counter in file 0 58:12 -> 60:6, #31 -Counter in file 0 61:1 -> 61:2, #32 +Counter in file 0 14:6 -> 14:7, (#1 - #2) +Counter in file 0 16:9 -> 16:17, ((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) +Counter in file 0 18:13 -> 18:18, (#2 + (#1 - #2)) +Counter in file 0 20:13 -> 20:18, ((#2 + (#1 - #2)) - #3) +Counter in file 0 20:18 -> 20:19, (#3 + #4) +Counter in file 0 20:18 -> 20:19, (((#2 + (#1 - #2)) - #3) - #4) +Counter in file 0 23:9 -> 23:17, ((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) +Counter in file 0 25:13 -> 25:18, (((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) + 0) +Counter in file 0 27:13 -> 27:18, (((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) +Counter in file 0 27:18 -> 27:19, (#5 + #6) +Counter in file 0 27:18 -> 27:19, ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6) +Counter in file 0 29:9 -> 29:17, ((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) +Counter in file 0 29:20 -> 29:25, (((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) + 0) +Counter in file 0 29:29 -> 29:34, #7 +Counter in file 0 29:34 -> 29:35, ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8) +Counter in file 0 29:34 -> 29:35, (#7 - #8) +Counter in file 0 30:9 -> 30:17, ((#9 - #10) + ((((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) - #9) + #10)) +Counter in file 0 30:20 -> 30:25, (((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) + 0) +Counter in file 0 30:29 -> 30:34, #9 +Counter in file 0 30:34 -> 30:35, ((((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) - #9) + #10) +Counter in file 0 30:34 -> 30:35, (#9 - #10) +Counter in file 0 33:9 -> 34:16, (((#9 - #10) + ((((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) - #9) + #10)) + 0) +Counter in file 0 35:5 -> 38:6, #11 +Counter in file 0 38:6 -> 38:7, (((#9 - #10) + ((((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) - #9) + #10)) - #11) +Counter in file 0 41:9 -> 41:16, (#11 + (((#9 - #10) + ((((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) - #9) + #10)) - #11)) +Counter in file 0 42:5 -> 45:6, #12 +Counter in file 0 47:5 -> 50:6, ((#11 + (((#9 - #10) + ((((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) - #9) + #10)) - #11)) - #12) +Counter in file 0 52:8 -> 52:16, (#12 + ((#11 + (((#9 - #10) + ((((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) - #9) + #10)) - #11)) - #12)) +Counter in file 0 52:17 -> 54:6, #13 +Counter in file 0 54:6 -> 54:7, ((#12 + ((#11 + (((#9 - #10) + ((((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) - #9) + #10)) - #11)) - #12)) - #13) +Counter in file 0 56:8 -> 56:15, (#13 + ((#12 + ((#11 + (((#9 - #10) + ((((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) - #9) + #10)) - #11)) - #12)) - #13)) +Counter in file 0 56:16 -> 58:6, #14 +Counter in file 0 58:12 -> 60:6, ((#13 + ((#12 + ((#11 + (((#9 - #10) + ((((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) - #9) + #10)) - #11)) - #12)) - #13)) - #14) +Counter in file 0 61:1 -> 61:2, (#14 + ((#13 + ((#12 + ((#11 + (((#9 - #10) + ((((#7 - #8) + ((((#5 + #6) + ((((#3 + #4) + (((#2 + (#1 - #2)) - #3) - #4)) - #5) - #6)) - #7) + #8)) - #9) + #10)) - #11)) - #12)) - #13)) - #14)) Emitting segments for file: ../coverage/lazy_boolean.rs Combined regions: 7:9 -> 9:42 (count=1) diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.loops_and_branches.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.loops_and_branches.txt index 3e0bc6e4959..235557ba349 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.loops_and_branches.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.loops_and_branches.txt @@ -1,12 +1,12 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/build/bin/llvm-cov show --debug --Xdemangler=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/stage0-tools-bin/rust-demangler --show-line-counts-or-regions --instr-profile=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-deadcode/coverage-reports-deadcode/loops_and_branches.profdata /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-deadcode/coverage-reports-deadcode/loops_and_branches Counter in file 0 10:12 -> 10:16, #1 Counter in file 0 11:16 -> 11:21, #2 -Counter in file 0 14:14 -> 14:15, #6 -Counter in file 0 15:13 -> 15:31, #7 -Counter in file 0 15:31 -> 15:32, #8 -Counter in file 0 17:10 -> 17:11, #10 -Counter in file 0 18:9 -> 18:15, #11 -Counter in file 0 19:5 -> 19:6, #12 +Counter in file 0 14:14 -> 14:15, (#2 - #5) +Counter in file 0 15:13 -> 15:31, (0 + (#2 - #5)) +Counter in file 0 15:31 -> 15:32, #4 +Counter in file 0 17:10 -> 17:11, #3 +Counter in file 0 18:9 -> 18:15, (#3 + 0) +Counter in file 0 19:5 -> 19:6, (#4 + (#3 + 0)) Counter in file 0 22:11 -> 25:2, #1 Emitting segments for file: ../coverage/loops_and_branches.rs Combined regions: diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.nested_loops.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.nested_loops.txt index a19f6253316..6bc26f94ac7 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.nested_loops.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.nested_loops.txt @@ -1,22 +1,22 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/build/bin/llvm-cov show --debug --Xdemangler=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/stage0-tools-bin/rust-demangler --show-line-counts-or-regions --instr-profile=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-deadcode/coverage-reports-deadcode/nested_loops.profdata /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-deadcode/coverage-reports-deadcode/nested_loops Counter in file 0 2:9 -> 3:27, #1 -Counter in file 0 5:19 -> 5:32, #2 -Counter in file 0 6:13 -> 7:24, #3 -Counter in file 0 8:13 -> 8:14, #4 -Counter in file 0 8:18 -> 8:23, #5 -Counter in file 0 9:16 -> 9:22, (#4 + 0) -Counter in file 0 10:17 -> 10:22, #6 -Counter in file 0 12:13 -> 12:19, #7 -Counter in file 0 13:13 -> 13:19, #8 -Counter in file 0 14:16 -> 14:22, (#8 + 0) -Counter in file 0 15:17 -> 16:27, #9 -Counter in file 0 17:21 -> 17:33, #10 -Counter in file 0 19:21 -> 21:14, #11 -Counter in file 0 21:14 -> 21:15, #12 -Counter in file 0 22:10 -> 22:11, #13 -Counter in file 0 23:9 -> 23:23, #14 -Counter in file 0 24:6 -> 24:7, #15 -Counter in file 0 25:1 -> 25:2, #16 +Counter in file 0 5:19 -> 5:32, (#1 + #2) +Counter in file 0 6:13 -> 7:24, ((#1 + #2) - #3) +Counter in file 0 8:13 -> 8:14, ((((#1 + #2) - #3) + (#5 + #6)) - #7) +Counter in file 0 8:18 -> 8:23, (((#1 + #2) - #3) + (#5 + #6)) +Counter in file 0 9:16 -> 9:22, (((((#1 + #2) - #3) + (#5 + #6)) - #7) + 0) +Counter in file 0 10:17 -> 10:22, #8 +Counter in file 0 12:13 -> 12:19, #9 +Counter in file 0 13:13 -> 13:19, #10 +Counter in file 0 14:16 -> 14:22, (#10 + 0) +Counter in file 0 15:17 -> 16:27, #11 +Counter in file 0 17:21 -> 17:33, #4 +Counter in file 0 19:21 -> 21:14, #5 +Counter in file 0 21:14 -> 21:15, #6 +Counter in file 0 22:10 -> 22:11, (#5 + #6) +Counter in file 0 23:9 -> 23:23, #2 +Counter in file 0 24:6 -> 24:7, #3 +Counter in file 0 25:1 -> 25:2, (#4 + #3) Emitting segments for file: ../coverage/nested_loops.rs Combined regions: 2:9 -> 3:27 (count=1) diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.partial_eq_counter_without_region.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.partial_eq_counter_without_region.txt index a444ea44901..5ab9a99d686 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.partial_eq_counter_without_region.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.partial_eq_counter_without_region.txt @@ -1,8 +1,5 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/build/bin/llvm-cov show --debug --Xdemangler=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/stage0-tools-bin/rust-demangler --show-line-counts-or-regions --instr-profile=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-deadcode/coverage-reports-deadcode/partial_eq_counter_without_region.profdata /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-deadcode/coverage-reports-deadcode/partial_eq_counter_without_region -Counter in file 0 4:39 -> 4:49, #1 -Counter in file 0 4:39 -> 4:49, #2 -Counter in file 0 4:39 -> 4:49, #3 -Counter in file 0 4:48 -> 4:49, #4 +Counter in file 0 4:48 -> 4:49, ((#1 + #2) + ((#3 + #4) + ((#5 + #6) + #7))) Counter in file 0 8:5 -> 8:17, #1 Counter in file 0 21:11 -> 26:2, #1 Counter in file 0 4:39 -> 4:40, #1 @@ -11,15 +8,8 @@ Counter in file 0 7:5 -> 7:6, #1 Counter in file 0 8:5 -> 8:17, #1 Counter in file 0 4:39 -> 4:40, #1 Counter in file 0 4:48 -> 4:49, (#1 + 0) -Counter in file 0 4:24 -> 4:33, #1 -Counter in file 0 4:24 -> 4:33, #2 -Counter in file 0 4:24 -> 4:33, #3 -Counter in file 0 4:24 -> 4:33, #4 -Counter in file 0 4:32 -> 4:33, #5 -Counter in file 0 4:51 -> 4:54, #1 -Counter in file 0 4:51 -> 4:54, #2 -Counter in file 0 4:51 -> 4:54, #3 -Counter in file 0 4:53 -> 4:54, #4 +Counter in file 0 4:32 -> 4:33, ((#4 + #5) + #6) +Counter in file 0 4:53 -> 4:54, (#1 + (#2 + (#3 + #4))) Counter in file 0 13:9 -> 18:6, #1 Counter in file 0 7:5 -> 7:6, #1 Counter in file 0 4:39 -> 4:40, #1 @@ -33,9 +23,7 @@ Counter in file 0 4:17 -> 4:22, #1 Counter in file 0 8:5 -> 8:17, #1 Counter in file 0 4:39 -> 4:40, #1 Counter in file 0 4:48 -> 4:49, (#1 + 0) -Counter in file 0 4:24 -> 4:33, #1 -Counter in file 0 4:24 -> 4:33, #2 -Counter in file 0 4:32 -> 4:33, #3 +Counter in file 0 4:32 -> 4:33, (#3 + (#1 + #2)) Emitting segments for file: ../coverage/partial_eq_counter_without_region.rs Combined regions: 4:17 -> 4:22 (count=2) diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.simple_loop.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.simple_loop.txt index 90e09099dcc..60d861e9d2e 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.simple_loop.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.simple_loop.txt @@ -2,12 +2,12 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/ Counter in file 0 7:9 -> 9:26, #1 Counter in file 0 12:9 -> 12:16, (#1 + 0) Counter in file 0 13:5 -> 18:6, #2 -Counter in file 0 18:6 -> 18:7, #3 -Counter in file 0 23:13 -> 25:14, #4 -Counter in file 0 27:13 -> 27:18, #5 -Counter in file 0 30:9 -> 32:10, #6 -Counter in file 0 34:6 -> 34:7, #7 -Counter in file 0 35:1 -> 35:2, (#5 + 0) +Counter in file 0 18:6 -> 18:7, (#1 - #2) +Counter in file 0 23:13 -> 25:14, ((#2 + (#1 - #2)) + #3) +Counter in file 0 27:13 -> 27:18, #4 +Counter in file 0 30:9 -> 32:10, #3 +Counter in file 0 34:6 -> 34:7, (#2 + (#1 - #2)) +Counter in file 0 35:1 -> 35:2, (#4 + 0) Emitting segments for file: ../coverage/simple_loop.rs Combined regions: 7:9 -> 9:26 (count=1) diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.simple_match.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.simple_match.txt index 39a986332cd..1683b68e966 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.simple_match.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.simple_match.txt @@ -2,18 +2,18 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/ Counter in file 0 7:9 -> 9:26, #1 Counter in file 0 10:8 -> 10:15, (#1 + 0) Counter in file 0 10:16 -> 12:6, #2 -Counter in file 0 12:6 -> 12:7, #3 -Counter in file 0 15:9 -> 15:10, #4 -Counter in file 0 17:9 -> 17:13, #5 -Counter in file 0 22:13 -> 22:22, (#4 + 0) -Counter in file 0 24:13 -> 24:14, #6 -Counter in file 0 26:17 -> 28:18, (#4 + 0) -Counter in file 0 28:18 -> 28:19, #7 -Counter in file 0 30:13 -> 37:14, (#6 + 0) -Counter in file 0 40:13 -> 40:15, #8 -Counter in file 0 42:6 -> 42:7, #9 -Counter in file 0 42:6 -> 42:7, #10 -Counter in file 0 43:1 -> 43:2, #11 +Counter in file 0 12:6 -> 12:7, (#1 - #2) +Counter in file 0 15:9 -> 15:10, (((#2 + (#1 - #2)) + (#3 + #4)) - #5) +Counter in file 0 17:9 -> 17:13, ((#2 + (#1 - #2)) + (#3 + #4)) +Counter in file 0 22:13 -> 22:22, ((((#2 + (#1 - #2)) + (#3 + #4)) - #5) + 0) +Counter in file 0 24:13 -> 24:14, #3 +Counter in file 0 26:17 -> 28:18, ((((#2 + (#1 - #2)) + (#3 + #4)) - #5) + 0) +Counter in file 0 28:18 -> 28:19, ((((#2 + (#1 - #2)) + (#3 + #4)) - #5) - #3) +Counter in file 0 30:13 -> 37:14, (#3 + 0) +Counter in file 0 40:13 -> 40:15, #4 +Counter in file 0 42:6 -> 42:7, (#2 + (#1 - #2)) +Counter in file 0 42:6 -> 42:7, (#3 + #4) +Counter in file 0 43:1 -> 43:2, #5 Emitting segments for file: ../coverage/simple_match.rs Combined regions: 7:9 -> 9:26 (count=1) diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.tight_infinite_loop.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.tight_infinite_loop.txt index a0687815fb9..39a3cf5458c 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.tight_infinite_loop.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.tight_infinite_loop.txt @@ -1,6 +1,6 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/build/bin/llvm-cov show --debug --Xdemangler=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/stage0-tools-bin/rust-demangler --show-line-counts-or-regions --instr-profile=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-deadcode/coverage-reports-deadcode/tight_infinite_loop.profdata /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-deadcode/coverage-reports-deadcode/tight_infinite_loop Counter in file 0 2:8 -> 2:13, #1 -Counter in file 0 5:1 -> 5:2, #4 +Counter in file 0 5:1 -> 5:2, (#1 - #2) Emitting segments for file: ../coverage/tight_infinite_loop.rs Combined regions: 2:8 -> 2:13 (count=1) diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.try_error_result.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.try_error_result.txt index 25e1c8930bc..9cfc05e874a 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.try_error_result.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.try_error_result.txt @@ -1,22 +1,21 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/build/bin/llvm-cov show --debug --Xdemangler=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/stage0-tools-bin/rust-demangler --show-line-counts-or-regions --instr-profile=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-deadcode/coverage-reports-deadcode/try_error_result.profdata /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-deadcode/coverage-reports-deadcode/try_error_result Counter in file 0 13:9 -> 14:23, #1 -Counter in file 0 17:9 -> 17:10, #2 -Counter in file 0 19:9 -> 19:14, #3 -Counter in file 0 21:9 -> 25:26, #4 -Counter in file 0 27:13 -> 27:41, #5 -Counter in file 0 27:41 -> 27:42, #6 -Counter in file 0 31:13 -> 31:42, #7 -Counter in file 0 31:42 -> 31:43, #8 -Counter in file 0 32:10 -> 32:11, #9 -Counter in file 0 32:10 -> 32:11, #10 -Counter in file 0 33:6 -> 33:7, #11 -Counter in file 0 34:5 -> 34:11, #12 -Counter in file 0 35:1 -> 35:2, #13 -Counter in file 0 35:1 -> 35:2, #14 +Counter in file 0 17:9 -> 17:10, ((#1 + (#2 + #3)) - #4) +Counter in file 0 19:9 -> 19:14, (#1 + (#2 + #3)) +Counter in file 0 21:9 -> 25:26, #7 +Counter in file 0 27:13 -> 27:41, #8 +Counter in file 0 27:41 -> 27:42, #5 +Counter in file 0 31:13 -> 31:42, (#7 - #8) +Counter in file 0 31:42 -> 31:43, #6 +Counter in file 0 32:10 -> 32:11, #2 +Counter in file 0 32:10 -> 32:11, #3 +Counter in file 0 33:6 -> 33:7, (#2 + #3) +Counter in file 0 34:5 -> 34:11, #4 +Counter in file 0 35:1 -> 35:2, ((#5 + #6) + #4) Counter in file 0 5:8 -> 5:20, #1 Counter in file 0 6:9 -> 6:16, #2 -Counter in file 0 8:9 -> 8:15, #3 -Counter in file 0 10:1 -> 10:2, #4 +Counter in file 0 8:9 -> 8:15, (#1 - #2) +Counter in file 0 10:1 -> 10:2, (#2 + (#1 - #2)) Emitting segments for file: ../coverage/try_error_result.rs Combined regions: 5:8 -> 5:20 (count=6) @@ -34,7 +33,7 @@ Combined regions: 32:10 -> 32:11 (count=5) 33:6 -> 33:7 (count=5) 34:5 -> 34:11 (count=0) - 35:1 -> 35:2 (count=2) + 35:1 -> 35:2 (count=1) Segment at 5:8 (count = 6), RegionEntry Segment at 5:20 (count = 0), Skipped Segment at 6:9 (count = 1), RegionEntry @@ -63,5 +62,5 @@ Segment at 33:6 (count = 5), RegionEntry Segment at 33:7 (count = 0), Skipped Segment at 34:5 (count = 0), RegionEntry Segment at 34:11 (count = 0), Skipped -Segment at 35:1 (count = 2), RegionEntry +Segment at 35:1 (count = 1), RegionEntry Segment at 35:2 (count = 0), Skipped diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.various_conditions.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.various_conditions.txt index 567c8cd9b6d..ba80cadbd3c 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.various_conditions.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.various_conditions.txt @@ -2,73 +2,72 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/ Counter in file 0 4:9 -> 4:26, #1 Counter in file 0 5:8 -> 5:12, (#1 + 0) Counter in file 0 5:13 -> 7:6, #2 -Counter in file 0 10:9 -> 10:10, #4 -Counter in file 0 10:16 -> 10:29, #5 -Counter in file 0 11:9 -> 12:10, #6 -Counter in file 0 13:15 -> 13:28, #7 -Counter in file 0 14:12 -> 14:25, #8 -Counter in file 0 14:29 -> 14:42, #9 -Counter in file 0 14:42 -> 14:43, #10 -Counter in file 0 14:42 -> 14:43, #11 -Counter in file 0 14:46 -> 14:60, #12 -Counter in file 0 14:60 -> 14:61, #13 -Counter in file 0 14:60 -> 14:61, #14 -Counter in file 0 14:61 -> 16:10, #15 -Counter in file 0 16:10 -> 16:11, #16 -Counter in file 0 17:9 -> 18:18, #17 -Counter in file 0 20:9 -> 20:15, #18 -Counter in file 0 23:9 -> 23:26, (#4 + 0) -Counter in file 0 24:8 -> 24:12, (#4 + 0) -Counter in file 0 24:13 -> 26:6, #19 -Counter in file 0 28:8 -> 28:21, #21 -Counter in file 0 29:9 -> 29:23, #22 -Counter in file 0 30:15 -> 30:28, #23 -Counter in file 0 31:12 -> 31:25, #24 -Counter in file 0 31:29 -> 31:42, #25 -Counter in file 0 31:42 -> 31:43, #26 -Counter in file 0 31:42 -> 31:43, #27 -Counter in file 0 31:46 -> 31:60, #28 -Counter in file 0 31:60 -> 31:61, #29 -Counter in file 0 31:60 -> 31:61, #30 -Counter in file 0 31:61 -> 33:10, #31 -Counter in file 0 33:10 -> 33:11, #32 -Counter in file 0 34:9 -> 34:23, #33 -Counter in file 0 36:9 -> 36:15, #34 -Counter in file 0 39:9 -> 39:26, #35 -Counter in file 0 40:8 -> 40:12, (#35 + 0) -Counter in file 0 40:13 -> 42:6, #36 -Counter in file 0 44:9 -> 44:10, #38 -Counter in file 0 44:16 -> 44:29, #39 -Counter in file 0 45:9 -> 45:23, #40 -Counter in file 0 46:15 -> 46:28, #41 -Counter in file 0 47:12 -> 47:25, #42 -Counter in file 0 47:29 -> 47:42, #43 -Counter in file 0 47:42 -> 47:43, #44 -Counter in file 0 47:42 -> 47:43, #45 -Counter in file 0 47:46 -> 47:60, #46 -Counter in file 0 47:60 -> 47:61, #47 -Counter in file 0 47:60 -> 47:61, #48 -Counter in file 0 47:61 -> 49:10, #49 -Counter in file 0 49:10 -> 49:11, #50 -Counter in file 0 50:9 -> 50:23, #51 -Counter in file 0 52:13 -> 54:15, #52 -Counter in file 0 57:9 -> 57:10, #53 -Counter in file 0 57:16 -> 57:29, (#38 + 0) -Counter in file 0 58:9 -> 58:23, #54 -Counter in file 0 59:15 -> 59:28, #55 -Counter in file 0 60:12 -> 60:25, #56 -Counter in file 0 60:29 -> 60:42, #57 -Counter in file 0 60:42 -> 60:43, #58 -Counter in file 0 60:42 -> 60:43, #59 -Counter in file 0 60:46 -> 60:60, #60 -Counter in file 0 60:60 -> 60:61, #61 -Counter in file 0 60:60 -> 60:61, #62 -Counter in file 0 60:61 -> 62:10, #63 -Counter in file 0 62:10 -> 62:11, #64 -Counter in file 0 63:9 -> 63:23, #65 -Counter in file 0 65:9 -> 65:15, #66 -Counter in file 0 67:1 -> 67:2, #67 -Counter in file 0 67:1 -> 67:2, #68 +Counter in file 0 10:9 -> 10:10, (#4 + #11) +Counter in file 0 10:16 -> 10:29, (#2 + 0) +Counter in file 0 11:9 -> 12:10, #4 +Counter in file 0 13:15 -> 13:28, ((#2 + 0) - #3) +Counter in file 0 14:12 -> 14:25, #5 +Counter in file 0 14:29 -> 14:42, (#5 - #13) +Counter in file 0 14:42 -> 14:43, (#13 + #14) +Counter in file 0 14:42 -> 14:43, ((#5 - #13) - #14) +Counter in file 0 14:46 -> 14:60, #21 +Counter in file 0 14:60 -> 14:61, (#17 + #18) +Counter in file 0 14:60 -> 14:61, (#21 - #18) +Counter in file 0 14:61 -> 16:10, #22 +Counter in file 0 16:10 -> 16:11, #23 +Counter in file 0 17:9 -> 18:18, #11 +Counter in file 0 20:9 -> 20:15, (((#2 + 0) - #3) - #5) +Counter in file 0 23:9 -> 23:26, ((#4 + #11) + 0) +Counter in file 0 24:8 -> 24:12, ((#4 + #11) + 0) +Counter in file 0 24:13 -> 26:6, #12 +Counter in file 0 28:8 -> 28:21, (#12 + 0) +Counter in file 0 29:9 -> 29:23, #16 +Counter in file 0 30:15 -> 30:28, ((#12 + 0) - #15) +Counter in file 0 31:12 -> 31:25, (((#12 + 0) - #15) - #8) +Counter in file 0 31:29 -> 31:42, ((((#12 + 0) - #15) - #8) - #24) +Counter in file 0 31:42 -> 31:43, (((((#12 + 0) - #15) - #8) - #24) - #25) +Counter in file 0 31:42 -> 31:43, (#24 + #25) +Counter in file 0 31:46 -> 31:60, #32 +Counter in file 0 31:60 -> 31:61, (#28 + #29) +Counter in file 0 31:60 -> 31:61, (#32 - #29) +Counter in file 0 31:61 -> 33:10, #33 +Counter in file 0 33:10 -> 33:11, #34 +Counter in file 0 34:9 -> 34:23, #19 +Counter in file 0 36:9 -> 36:15, #8 +Counter in file 0 39:9 -> 39:26, (#16 + #19) +Counter in file 0 40:8 -> 40:12, ((#16 + #19) + 0) +Counter in file 0 40:13 -> 42:6, #20 +Counter in file 0 44:9 -> 44:10, (#27 + #30) +Counter in file 0 44:16 -> 44:29, (#20 + 0) +Counter in file 0 45:9 -> 45:23, #27 +Counter in file 0 46:15 -> 46:28, ((#20 + 0) - #26) +Counter in file 0 47:12 -> 47:25, (((#20 + 0) - #26) - #7) +Counter in file 0 47:29 -> 47:42, ((((#20 + 0) - #26) - #7) - #35) +Counter in file 0 47:42 -> 47:43, (#35 + #36) +Counter in file 0 47:42 -> 47:43, (((((#20 + 0) - #26) - #7) - #35) - #36) +Counter in file 0 47:46 -> 47:60, #41 +Counter in file 0 47:60 -> 47:61, (#37 + #38) +Counter in file 0 47:60 -> 47:61, (#41 - #38) +Counter in file 0 47:61 -> 49:10, #42 +Counter in file 0 49:10 -> 49:11, #43 +Counter in file 0 50:9 -> 50:23, #30 +Counter in file 0 52:13 -> 54:15, #7 +Counter in file 0 57:9 -> 57:10, (#9 + #10) +Counter in file 0 57:16 -> 57:29, ((#27 + #30) + 0) +Counter in file 0 58:9 -> 58:23, #9 +Counter in file 0 59:15 -> 59:28, ((#27 + #30) - #31) +Counter in file 0 60:12 -> 60:25, (((#27 + #30) - #31) - #6) +Counter in file 0 60:29 -> 60:42, ((((#27 + #30) - #31) - #6) - #39) +Counter in file 0 60:42 -> 60:43, (#39 + #40) +Counter in file 0 60:42 -> 60:43, (((((#27 + #30) - #31) - #6) - #39) - #40) +Counter in file 0 60:46 -> 60:60, #46 +Counter in file 0 60:60 -> 60:61, (#46 - #45) +Counter in file 0 60:60 -> 60:61, (#44 + #45) +Counter in file 0 60:61 -> 62:10, #47 +Counter in file 0 62:10 -> 62:11, #48 +Counter in file 0 63:9 -> 63:23, #10 +Counter in file 0 65:9 -> 65:15, #6 +Counter in file 0 67:1 -> 67:2, ((#9 + #10) + (((#6 + #7) + #8) + (((#2 + 0) - #3) - #5))) Emitting segments for file: ../coverage/various_conditions.rs Combined regions: 4:9 -> 4:26 (count=1) @@ -131,7 +130,7 @@ Combined regions: 62:10 -> 62:11 (count=0) 63:9 -> 63:23 (count=0) 65:9 -> 65:15 (count=0) - 67:1 -> 67:2 (count=2) + 67:1 -> 67:2 (count=1) Segment at 4:9 (count = 1), RegionEntry Segment at 4:26 (count = 0), Skipped Segment at 5:8 (count = 1), RegionEntry @@ -236,5 +235,5 @@ Segment at 63:9 (count = 0), RegionEntry Segment at 63:23 (count = 0), Skipped Segment at 65:9 (count = 0), RegionEntry Segment at 65:15 (count = 0), Skipped -Segment at 67:1 (count = 2), RegionEntry +Segment at 67:1 (count = 1), RegionEntry Segment at 67:2 (count = 0), Skipped diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.while.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.while.txt index b75a88b2e92..76cf1e92ecd 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.while.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.while.txt @@ -1,8 +1,8 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/build/bin/llvm-cov show --debug --Xdemangler=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/stage0-tools-bin/rust-demangler --show-line-counts-or-regions --instr-profile=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-deadcode/coverage-reports-deadcode/while.profdata /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-deadcode/coverage-reports-deadcode/while Counter in file 0 2:9 -> 2:16, #1 -Counter in file 0 3:11 -> 3:20, #2 -Counter in file 0 3:21 -> 4:6, #3 -Counter in file 0 5:1 -> 5:2, #4 +Counter in file 0 3:11 -> 3:20, (#1 + #2) +Counter in file 0 3:21 -> 4:6, #2 +Counter in file 0 5:1 -> 5:2, ((#1 + #2) - #2) Emitting segments for file: ../coverage/while.rs Combined regions: 2:9 -> 2:16 (count=1) diff --git a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.while_early_return.txt b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.while_early_return.txt index 908613018a4..60f389fc9d4 100644 --- a/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.while_early_return.txt +++ b/src/test/run-make-fulldeps/coverage-reports-deadcode/expected_show_coverage_counters.while_early_return.txt @@ -1,14 +1,13 @@ Args: /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/llvm/build/bin/llvm-cov show --debug --Xdemangler=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/stage0-tools-bin/rust-demangler --show-line-counts-or-regions --instr-profile=/usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-deadcode/coverage-reports-deadcode/while_early_return.profdata /usr/local/google/home/richkadel/rust/build/x86_64-unknown-linux-gnu/test/run-make-fulldeps/coverage-reports-deadcode/coverage-reports-deadcode/while_early_return Counter in file 0 5:9 -> 5:27, #1 -Counter in file 0 7:9 -> 9:10, #2 -Counter in file 0 12:13 -> 14:14, #3 -Counter in file 0 18:21 -> 20:22, #4 -Counter in file 0 22:21 -> 22:27, #5 -Counter in file 0 26:21 -> 26:27, #6 -Counter in file 0 30:9 -> 32:10, #7 -Counter in file 0 35:5 -> 35:11, #8 -Counter in file 0 36:1 -> 36:2, #9 -Counter in file 0 36:1 -> 36:2, #10 +Counter in file 0 7:9 -> 9:10, (#1 + #2) +Counter in file 0 12:13 -> 14:14, ((#1 + #2) - #3) +Counter in file 0 18:21 -> 20:22, #6 +Counter in file 0 22:21 -> 22:27, #4 +Counter in file 0 26:21 -> 26:27, #5 +Counter in file 0 30:9 -> 32:10, #2 +Counter in file 0 35:5 -> 35:11, #3 +Counter in file 0 36:1 -> 36:2, ((#4 + #5) + #3) Emitting segments for file: ../coverage/while_early_return.rs Combined regions: 5:9 -> 5:27 (count=1) @@ -19,7 +18,7 @@ Combined regions: 26:21 -> 26:27 (count=1) 30:9 -> 32:10 (count=6) 35:5 -> 35:11 (count=0) - 36:1 -> 36:2 (count=2) + 36:1 -> 36:2 (count=1) Segment at 5:9 (count = 1), RegionEntry Segment at 5:27 (count = 0), Skipped Segment at 7:9 (count = 7), RegionEntry @@ -36,5 +35,5 @@ Segment at 30:9 (count = 6), RegionEntry Segment at 32:10 (count = 0), Skipped Segment at 35:5 (count = 0), RegionEntry Segment at 35:11 (count = 0), Skipped -Segment at 36:1 (count = 2), RegionEntry +Segment at 36:1 (count = 1), RegionEntry Segment at 36:2 (count = 0), Skipped diff --git a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.drop_trait/drop_trait.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.drop_trait/drop_trait.main.-------.InstrumentCoverage.0.html index 325b6c64345..494e6f20ea7 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.drop_trait/drop_trait.main.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.drop_trait/drop_trait.main.-------.InstrumentCoverage.0.html @@ -114,6 +114,6 @@ Ok(())⦉@2,6,7,8
-}@1,3,4,5,9,10⦊⦉@1,3,4,5,9,10@2,6,7,8⦊⦉@2,6,7,8@11⦊⦉@11 +}@11⦊⦉@11 diff --git a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.generics/generics.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.generics/generics.main.-------.InstrumentCoverage.0.html index 55d7e8bfbae..6dc893d28ff 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.generics/generics.main.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.generics/generics.main.-------.InstrumentCoverage.0.html @@ -162,6 +162,6 @@ Ok(())⦉@5,9,10,11
-}@4,6,7,8,12,13⦊⦉@4,6,7,8,12,13@5,9,10,11⦊⦉@5,9,10,11@14⦊⦉@14 +}@14⦊⦉@14 diff --git a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.if_else/if_else.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.if_else/if_else.main.-------.InstrumentCoverage.0.html index 094dacde986..b51c5c84c0d 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.if_else/if_else.main.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.if_else/if_else.main.-------.InstrumentCoverage.0.html @@ -128,36 +128,36 @@ 20:9-22:16: @5[1]: _6 = const ()"> =
100⦉@5 - }@4,6⦊⦉@4,6 + } if - @7⦊is_true⦉@7 - @8,10⦊{ - countdown - = - 10 - ; - }⦉@8,10 else - @9⦊{ - countdown - = - 100 - ; - }⦉@9@8,10⦊⦉@8,10 + }⦉@9 }@11⦊⦉@11 diff --git a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.try_error_result/try_error_result.call.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.try_error_result/try_error_result.call.-------.InstrumentCoverage.0.html index 8a0b1ae8dab..9f993342340 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.try_error_result/try_error_result.call.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-base/expected_mir_dump.try_error_result/try_error_result.call.-------.InstrumentCoverage.0.html @@ -67,7 +67,7 @@ } else { @2⦊Ok(())⦉@2 - }@1,3⦊⦉@1,3 -}@4⦊⦉@4 + } +}@4⦊⦉@4 diff --git a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.drop_trait/drop_trait.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.drop_trait/drop_trait.main.-------.InstrumentCoverage.0.html index 325b6c64345..494e6f20ea7 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.drop_trait/drop_trait.main.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.drop_trait/drop_trait.main.-------.InstrumentCoverage.0.html @@ -114,6 +114,6 @@ Ok(())⦉@2,6,7,8 -}@1,3,4,5,9,10⦊⦉@1,3,4,5,9,10@2,6,7,8⦊⦉@2,6,7,8@11⦊⦉@11 +}@11⦊⦉@11 diff --git a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.generics/generics.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.generics/generics.main.-------.InstrumentCoverage.0.html index 55d7e8bfbae..6dc893d28ff 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.generics/generics.main.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.generics/generics.main.-------.InstrumentCoverage.0.html @@ -162,6 +162,6 @@ Ok(())⦉@5,9,10,11 -}@4,6,7,8,12,13⦊⦉@4,6,7,8,12,13@5,9,10,11⦊⦉@5,9,10,11@14⦊⦉@14 +}@14⦊⦉@14 diff --git a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.if_else/if_else.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.if_else/if_else.main.-------.InstrumentCoverage.0.html index 094dacde986..b51c5c84c0d 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.if_else/if_else.main.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.if_else/if_else.main.-------.InstrumentCoverage.0.html @@ -128,36 +128,36 @@ 20:9-22:16: @5[1]: _6 = const ()"> = 100⦉@5 - }@4,6⦊⦉@4,6 + } if - @7⦊is_true⦉@7 - @8,10⦊{ - countdown - = - 10 - ; - }⦉@8,10 else - @9⦊{ - countdown - = - 100 - ; - }⦉@9@8,10⦊⦉@8,10 + }⦉@9 }@11⦊⦉@11 diff --git a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.try_error_result/try_error_result.call.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.try_error_result/try_error_result.call.-------.InstrumentCoverage.0.html index 8a0b1ae8dab..9f993342340 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.try_error_result/try_error_result.call.-------.InstrumentCoverage.0.html +++ b/src/test/run-make-fulldeps/coverage-spanview-deadcode/expected_mir_dump.try_error_result/try_error_result.call.-------.InstrumentCoverage.0.html @@ -67,7 +67,7 @@ } else { @2⦊Ok(())⦉@2 - }@1,3⦊⦉@1,3 -}@4⦊⦉@4 + } +}@4⦊⦉@4 -- cgit 1.4.1-3-g733a5 From a7d956583ceae1487ad9b0748039bc9f0e8ac7aa Mon Sep 17 00:00:00 2001 From: Rich Kadel Date: Fri, 30 Oct 2020 16:09:05 -0700 Subject: Responded to all feedback as of 2020-10-30 --- .../rustc_mir/src/transform/coverage/counters.rs | 297 +++++++++++---------- compiler/rustc_mir/src/transform/coverage/debug.rs | 129 ++++++++- compiler/rustc_mir/src/transform/coverage/graph.rs | 66 +++-- compiler/rustc_mir/src/transform/coverage/mod.rs | 20 +- compiler/rustc_mir/src/transform/coverage/query.rs | 26 +- compiler/rustc_mir/src/transform/coverage/spans.rs | 24 +- compiler/rustc_session/src/options.rs | 7 +- .../coverage-spanview-base/Makefile | 1 + .../run-make-fulldeps/coverage/coverage_tools.mk | 5 + 9 files changed, 367 insertions(+), 208 deletions(-) (limited to 'compiler/rustc_mir/src/transform/coverage/debug.rs') diff --git a/compiler/rustc_mir/src/transform/coverage/counters.rs b/compiler/rustc_mir/src/transform/coverage/counters.rs index 7454ec2f438..d6c2f7f7aaf 100644 --- a/compiler/rustc_mir/src/transform/coverage/counters.rs +++ b/compiler/rustc_mir/src/transform/coverage/counters.rs @@ -12,16 +12,6 @@ use rustc_data_structures::graph::WithNumNodes; use rustc_index::bit_set::BitSet; use rustc_middle::mir::coverage::*; -// When evaluating an expression operand to determine if it references a `Counter` or an -// `Expression`, the range of counter or expression IDs must be known in order to answer the -// question: "Does this ID fall inside the range of counters," for example. If "yes," the ID refers -// to a counter, otherwise the ID refers to an expression. -// -// But in situations where the range is not currently known, the only fallback is to assume a -// specific range limit. `MAX_COUNTER_GUARD` enforces a limit on the number of counters, and -// therefore a limit on the range of counter IDs. -pub(crate) const MAX_COUNTER_GUARD: u32 = (u32::MAX / 2) + 1; - /// Manages the counter and expression indexes/IDs to generate `CoverageKind` components for MIR /// `Coverage` statements. pub(crate) struct CoverageCounters { @@ -105,7 +95,6 @@ impl CoverageCounters { /// Counter IDs start from one and go up. fn next_counter(&mut self) -> CounterValueReference { assert!(self.next_counter_id < u32::MAX - self.num_expressions); - assert!(self.next_counter_id <= MAX_COUNTER_GUARD); let next = self.next_counter_id; self.next_counter_id += 1; CounterValueReference::from(next) @@ -131,6 +120,7 @@ struct BcbCounters<'a> { basic_coverage_blocks: &'a mut CoverageGraph, } +// FIXME(richkadel): Add unit tests for `BcbCounters` functions/algorithms. impl<'a> BcbCounters<'a> { fn new( coverage_counters: &'a mut CoverageCounters, @@ -139,7 +129,7 @@ impl<'a> BcbCounters<'a> { Self { coverage_counters, basic_coverage_blocks } } - /// If two `CoverageGraph` branch from another `BasicCoverageBlock`, one of the branches + /// If two `BasicCoverageBlock`s branch from another `BasicCoverageBlock`, one of the branches /// can be counted by `Expression` by subtracting the other branch from the branching /// block. Otherwise, the `BasicCoverageBlock` executed the least should have the `Counter`. /// One way to predict which branch executes the least is by considering loops. A loop is exited @@ -162,10 +152,16 @@ impl<'a> BcbCounters<'a> { bcbs_with_coverage.insert(covspan.bcb); } - // FIXME(richkadel): Add more comments to explain the logic here and in the rest of this - // function, and refactor this function to break it up into smaller functions that are - // easier to understand. - + // Walk the `CoverageGraph`. For each `BasicCoverageBlock` node with an associated + // `CoverageSpan`, add a counter. If the `BasicCoverageBlock` branches, add a counter or + // expression to each branch `BasicCoverageBlock` (if the branch BCB has only one incoming + // edge) or edge from the branching BCB to the branch BCB (if the branch BCB has multiple + // incoming edges). + // + // The `TraverseCoverageGraphWithLoops` traversal ensures that, when a loop is encountered, + // all `BasicCoverageBlock` nodes in the loop are visited before visiting any node outside + // the loop. The `traversal` state includes a `context_stack`, providing a way to know if + // the current BCB is in one or more nested loops or not. let mut traversal = TraverseCoverageGraphWithLoops::new(&self.basic_coverage_blocks); while let Some(bcb) = traversal.next(self.basic_coverage_blocks) { if bcbs_with_coverage.contains(bcb) { @@ -220,11 +216,20 @@ impl<'a> BcbCounters<'a> { .join("\n "), ); + // Use the `traversal` state to decide if a subset of the branches exit a loop, making it + // likely that branch is executed less than branches that do not exit the same loop. In this + // case, any branch that does not exit the loop (and has not already been assigned a + // counter) should be counted by expression, if possible. (If a preferred expression branch + // is not selected based on the loop context, select any branch without an existing + // counter.) let expression_branch = self.choose_preferred_expression_branch(traversal, &branches); - // Assign a Counter or Expression to each branch, plus additional - // `Expression`s, as needed, to sum up intermediate results. + + // Assign a Counter or Expression to each branch, plus additional `Expression`s, as needed, + // to sum up intermediate results. let mut some_sumup_counter_operand = None; for branch in branches { + // Skip the selected `expression_branch`, if any. It's expression will be assigned after + // all others. if branch != expression_branch { let branch_counter_operand = if branch.is_only_path_to_target() { debug!( @@ -263,6 +268,9 @@ impl<'a> BcbCounters<'a> { } } } + + // Assign the final expression to the `expression_branch` by subtracting the total of all + // other branches from the counter of the branching BCB. let sumup_counter_operand = some_sumup_counter_operand.expect("sumup_counter_operand should have a value"); debug!( @@ -301,99 +309,99 @@ impl<'a> BcbCounters<'a> { collect_intermediate_expressions: &mut Vec, debug_indent_level: usize, ) -> Result { - Ok({ - if let Some(counter_kind) = self.basic_coverage_blocks[bcb].counter() { + // If the BCB already has a counter, return it. + if let Some(counter_kind) = self.basic_coverage_blocks[bcb].counter() { + debug!( + "{}{:?} already has a counter: {}", + NESTED_INDENT.repeat(debug_indent_level), + bcb, + self.format_counter(counter_kind), + ); + return Ok(counter_kind.as_operand_id()); + } + + // A BCB with only one incoming edge gets a simple `Counter` (via `make_counter()`). + // Also, a BCB that loops back to itself gets a simple `Counter`. This may indicate the + // program results in a tight infinite loop, but it should still compile. + let one_path_to_target = self.bcb_has_one_path_to_target(bcb); + if one_path_to_target || self.bcb_predecessors(bcb).contains(&bcb) { + let counter_kind = self.coverage_counters.make_counter(|| Some(format!("{:?}", bcb))); + if one_path_to_target { debug!( - "{}{:?} already has a counter: {}", + "{}{:?} gets a new counter: {}", NESTED_INDENT.repeat(debug_indent_level), bcb, - self.format_counter(counter_kind), + self.format_counter(&counter_kind), ); - counter_kind.as_operand_id() } else { - let one_path_to_target = self.bcb_has_one_path_to_target(bcb); - if one_path_to_target || self.bcb_predecessors(bcb).contains(&bcb) { - let counter_kind = - self.coverage_counters.make_counter(|| Some(format!("{:?}", bcb))); - if one_path_to_target { - debug!( - "{}{:?} gets a new counter: {}", - NESTED_INDENT.repeat(debug_indent_level), - bcb, - self.format_counter(&counter_kind), - ); - } else { - debug!( - "{}{:?} has itself as its own predecessor. It can't be part of its own \ - Expression sum, so it will get its own new counter: {}. (Note, the \ - compiled code will generate an infinite loop.)", - NESTED_INDENT.repeat(debug_indent_level), - bcb, - self.format_counter(&counter_kind), - ); - } - self.basic_coverage_blocks[bcb].set_counter(counter_kind)? - } else { - let mut predecessors = self.bcb_predecessors(bcb).clone().into_iter(); - debug!( - "{}{:?} has multiple incoming edges and will get an expression that sums \ - them up...", - NESTED_INDENT.repeat(debug_indent_level), - bcb, - ); - let first_edge_counter_operand = self - .recursive_get_or_make_edge_counter_operand( - predecessors.next().unwrap(), - bcb, - collect_intermediate_expressions, - debug_indent_level + 1, - )?; - let mut some_sumup_edge_counter_operand = None; - for predecessor in predecessors { - let edge_counter_operand = self - .recursive_get_or_make_edge_counter_operand( - predecessor, - bcb, - collect_intermediate_expressions, - debug_indent_level + 1, - )?; - if let Some(sumup_edge_counter_operand) = - some_sumup_edge_counter_operand.replace(edge_counter_operand) - { - let intermediate_expression = self.coverage_counters.make_expression( - sumup_edge_counter_operand, - Op::Add, - edge_counter_operand, - || None, - ); - debug!( - "{}new intermediate expression: {}", - NESTED_INDENT.repeat(debug_indent_level), - self.format_counter(&intermediate_expression) - ); - let intermediate_expression_operand = - intermediate_expression.as_operand_id(); - collect_intermediate_expressions.push(intermediate_expression); - some_sumup_edge_counter_operand - .replace(intermediate_expression_operand); - } - } - let counter_kind = self.coverage_counters.make_expression( - first_edge_counter_operand, - Op::Add, - some_sumup_edge_counter_operand.unwrap(), - || Some(format!("{:?}", bcb)), - ); - debug!( - "{}{:?} gets a new counter (sum of predecessor counters): {}", - NESTED_INDENT.repeat(debug_indent_level), - bcb, - self.format_counter(&counter_kind) - ); - self.basic_coverage_blocks[bcb].set_counter(counter_kind)? - } + debug!( + "{}{:?} has itself as its own predecessor. It can't be part of its own \ + Expression sum, so it will get its own new counter: {}. (Note, the compiled \ + code will generate an infinite loop.)", + NESTED_INDENT.repeat(debug_indent_level), + bcb, + self.format_counter(&counter_kind), + ); } - }) + return self.basic_coverage_blocks[bcb].set_counter(counter_kind); + } + + // A BCB with multiple incoming edges can compute its count by `Expression`, summing up the + // counters and/or expressions of its incoming edges. This will recursively get or create + // counters for those incoming edges first, then call `make_expression()` to sum them up, + // with additional intermediate expressions as needed. + let mut predecessors = self.bcb_predecessors(bcb).clone().into_iter(); + debug!( + "{}{:?} has multiple incoming edges and will get an expression that sums them up...", + NESTED_INDENT.repeat(debug_indent_level), + bcb, + ); + let first_edge_counter_operand = self.recursive_get_or_make_edge_counter_operand( + predecessors.next().unwrap(), + bcb, + collect_intermediate_expressions, + debug_indent_level + 1, + )?; + let mut some_sumup_edge_counter_operand = None; + for predecessor in predecessors { + let edge_counter_operand = self.recursive_get_or_make_edge_counter_operand( + predecessor, + bcb, + collect_intermediate_expressions, + debug_indent_level + 1, + )?; + if let Some(sumup_edge_counter_operand) = + some_sumup_edge_counter_operand.replace(edge_counter_operand) + { + let intermediate_expression = self.coverage_counters.make_expression( + sumup_edge_counter_operand, + Op::Add, + edge_counter_operand, + || None, + ); + debug!( + "{}new intermediate expression: {}", + NESTED_INDENT.repeat(debug_indent_level), + self.format_counter(&intermediate_expression) + ); + let intermediate_expression_operand = intermediate_expression.as_operand_id(); + collect_intermediate_expressions.push(intermediate_expression); + some_sumup_edge_counter_operand.replace(intermediate_expression_operand); + } + } + let counter_kind = self.coverage_counters.make_expression( + first_edge_counter_operand, + Op::Add, + some_sumup_edge_counter_operand.unwrap(), + || Some(format!("{:?}", bcb)), + ); + debug!( + "{}{:?} gets a new counter (sum of predecessor counters): {}", + NESTED_INDENT.repeat(debug_indent_level), + bcb, + self.format_counter(&counter_kind) + ); + self.basic_coverage_blocks[bcb].set_counter(counter_kind) } fn get_or_make_edge_counter_operand( @@ -417,46 +425,44 @@ impl<'a> BcbCounters<'a> { collect_intermediate_expressions: &mut Vec, debug_indent_level: usize, ) -> Result { - Ok({ - let successors = self.bcb_successors(from_bcb).iter(); - if successors.len() > 1 { - if let Some(counter_kind) = - self.basic_coverage_blocks[to_bcb].edge_counter_from(from_bcb) - { - debug!( - "{}Edge {:?}->{:?} already has a counter: {}", - NESTED_INDENT.repeat(debug_indent_level), - from_bcb, - to_bcb, - self.format_counter(counter_kind) - ); - counter_kind.as_operand_id() - } else { - let counter_kind = self - .coverage_counters - .make_counter(|| Some(format!("{:?}->{:?}", from_bcb, to_bcb))); - debug!( - "{}Edge {:?}->{:?} gets a new counter: {}", - NESTED_INDENT.repeat(debug_indent_level), - from_bcb, - to_bcb, - self.format_counter(&counter_kind) - ); - self.basic_coverage_blocks[to_bcb] - .set_edge_counter_from(from_bcb, counter_kind)? - } - } else { - self.recursive_get_or_make_counter_operand( - from_bcb, - collect_intermediate_expressions, - debug_indent_level + 1, - )? - } - }) + // If the source BCB has only one successor (assumed to be the given target), an edge + // counter is unnecessary. Just get or make a counter for the source BCB. + let successors = self.bcb_successors(from_bcb).iter(); + if successors.len() == 1 { + return self.recursive_get_or_make_counter_operand( + from_bcb, + collect_intermediate_expressions, + debug_indent_level + 1, + ); + } + + // If the edge already has a counter, return it. + if let Some(counter_kind) = self.basic_coverage_blocks[to_bcb].edge_counter_from(from_bcb) { + debug!( + "{}Edge {:?}->{:?} already has a counter: {}", + NESTED_INDENT.repeat(debug_indent_level), + from_bcb, + to_bcb, + self.format_counter(counter_kind) + ); + return Ok(counter_kind.as_operand_id()); + } + + // Make a new counter to count this edge. + let counter_kind = + self.coverage_counters.make_counter(|| Some(format!("{:?}->{:?}", from_bcb, to_bcb))); + debug!( + "{}Edge {:?}->{:?} gets a new counter: {}", + NESTED_INDENT.repeat(debug_indent_level), + from_bcb, + to_bcb, + self.format_counter(&counter_kind) + ); + self.basic_coverage_blocks[to_bcb].set_edge_counter_from(from_bcb, counter_kind) } - /// Select a branch for the expression, either the recommended `reloop_branch`, or - /// if none was found, select any branch. + /// Select a branch for the expression, either the recommended `reloop_branch`, or if none was + /// found, select any branch. fn choose_preferred_expression_branch( &self, traversal: &TraverseCoverageGraphWithLoops, @@ -493,9 +499,8 @@ impl<'a> BcbCounters<'a> { } } - /// At most one of the branches (or its edge, from the branching_bcb, - /// if the branch has multiple incoming edges) can have a counter computed by - /// expression. + /// At most, one of the branches (or its edge, from the branching_bcb, if the branch has + /// multiple incoming edges) can have a counter computed by expression. /// /// If at least one of the branches leads outside of a loop (`found_loop_exit` is /// true), and at least one other branch does not exit the loop (the first of which diff --git a/compiler/rustc_mir/src/transform/coverage/debug.rs b/compiler/rustc_mir/src/transform/coverage/debug.rs index 7080975aee5..cc697dfd7fe 100644 --- a/compiler/rustc_mir/src/transform/coverage/debug.rs +++ b/compiler/rustc_mir/src/transform/coverage/debug.rs @@ -1,3 +1,113 @@ +//! The `InstrumentCoverage` MIR pass implementation includes debugging tools and options +//! to help developers understand and/or improve the analysis and instrumentation of a MIR. +//! +//! To enable coverage, include the rustc command line option: +//! +//! * `-Z instrument-coverage` +//! +//! MIR Dump Files, with additional `CoverageGraph` graphviz and `CoverageSpan` spanview +//! ------------------------------------------------------------------------------------ +//! +//! Additional debugging options include: +//! +//! * `-Z dump-mir=InstrumentCoverage` - Generate `.mir` files showing the state of the MIR, +//! before and after the `InstrumentCoverage` pass, for each compiled function. +//! +//! * `-Z dump-mir-graphviz` - If `-Z dump-mir` is also enabled for the current MIR node path, +//! each MIR dump is accompanied by a before-and-after graphical view of the MIR, in Graphviz +//! `.dot` file format (which can be visually rendered as a graph using any of a number of free +//! Graphviz viewers and IDE extensions). +//! +//! For the `InstrumentCoverage` pass, this option also enables generation of an additional +//! Graphviz `.dot` file for each function, rendering the `CoverageGraph`: the control flow +//! graph (CFG) of `BasicCoverageBlocks` (BCBs), as nodes, internally labeled to show the +//! `CoverageSpan`-based MIR elements each BCB represents (`BasicBlock`s, `Statement`s and +//! `Terminator`s), assigned coverage counters and/or expressions, and edge counters, as needed. +//! +//! (Note the additional option, `-Z graphviz-dark-mode`, can be added, to change the rendered +//! output from its default black-on-white background to a dark color theme, if desired.) +//! +//! * `-Z dump-mir-spanview` - If `-Z dump-mir` is also enabled for the current MIR node path, +//! each MIR dump is accompanied by a before-and-after `.html` document showing the function's +//! original source code, highlighted by it's MIR spans, at the `statement`-level (by default), +//! `terminator` only, or encompassing span for the `Terminator` plus all `Statement`s, in each +//! `block` (`BasicBlock`). +//! +//! For the `InstrumentCoverage` pass, this option also enables generation of an additional +//! spanview `.html` file for each function, showing the aggregated `CoverageSpan`s that will +//! require counters (or counter expressions) for accurate coverage analysis. +//! +//! Debug Logging +//! ------------- +//! +//! The `InstrumentCoverage` pass includes debug logging messages at various phases and decision +//! points, which can be enabled via environment variable: +//! +//! ```shell +//! RUSTC_LOG=rustc_mir::transform::coverage=debug +//! ``` +//! +//! Other module paths with coverage-related debug logs may also be of interest, particularly for +//! debugging the coverage map data, injected as global variables in the LLVM IR (during rustc's +//! code generation pass). For example: +//! +//! ```shell +//! RUSTC_LOG=rustc_mir::transform::coverage,rustc_codegen_ssa::coverageinfo,rustc_codegen_llvm::coverageinfo=debug +//! ``` +//! +//! Coverage Debug Options +//! --------------------------------- +//! +//! Additional debugging options can be enabled using the environment variable: +//! +//! ```shell +//! RUSTC_COVERAGE_DEBUG_OPTIONS= +//! ``` +//! +//! These options are comma-separated, and specified in the format `option-name=value`. For example: +//! +//! ```shell +//! $ RUSTC_COVERAGE_DEBUG_OPTIONS=counter-format=id+operation,allow-unused-expressions=yes cargo build +//! ``` +//! +//! Coverage debug options include: +//! +//! * `allow-unused-expressions=yes` or `no` (default: `no`) +//! +//! The `InstrumentCoverage` algorithms _should_ only create and assign expressions to a +//! `BasicCoverageBlock`, or an incoming edge, if that expression is either (a) required to +//! count a `CoverageSpan`, or (b) a dependency of some other required counter expression. +//! +//! If an expression is generated that does not map to a `CoverageSpan` or dependency, this +//! probably indicates there was a bug in the algorithm that creates and assigns counters +//! and expressions. +//! +//! When this kind of bug is encountered, the rustc compiler will panic by default. Setting: +//! `allow-unused-expressions=yes` will log a warning message instead of panicking (effectively +//! ignoring the unused expressions), which may be helpful when debugging the root cause of +//! the problem. +//! +//! * `counter-format=`, where `` can be any plus-separated combination of `id`, +//! `block`, and/or `operation` (default: `block+operation`) +//! +//! This option effects both the `CoverageGraph` (graphviz `.dot` files) and debug logging, when +//! generating labels for counters and expressions. +//! +//! Depending on the values and combinations, counters can be labeled by: +//! +//! * `id` - counter or expression ID (ascending counter IDs, starting at 1, or descending +//! expression IDs, starting at `u32:MAX`) +//! * `block` - the `BasicCoverageBlock` label (for example, `bcb0`) or edge label (for +//! example `bcb0->bcb1`), for counters or expressions assigned to count a +//! `BasicCoverageBlock` or edge. Intermediate expressions (not directly associated with +//! a BCB or edge) will be labeled by their expression ID, unless `operation` is also +//! specified. +//! * `operation` - applied to expressions only, labels include the left-hand-side counter +//! or expression label (lhs operand), the operator (`+` or `-`), and the right-hand-side +//! counter or expression (rhs operand). Expression operand labels are generated +//! recursively, generating labels with nested operations, enclosed in parentheses +//! (for example: `bcb2 + (bcb0 - bcb1)`). + use super::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph}; use super::spans::CoverageSpan; @@ -20,13 +130,11 @@ const RUSTC_COVERAGE_DEBUG_OPTIONS: &str = "RUSTC_COVERAGE_DEBUG_OPTIONS"; pub(crate) fn debug_options<'a>() -> &'a DebugOptions { static DEBUG_OPTIONS: SyncOnceCell = SyncOnceCell::new(); - &DEBUG_OPTIONS.get_or_init(|| DebugOptions::new()) + &DEBUG_OPTIONS.get_or_init(|| DebugOptions::from_env()) } /// Parses and maintains coverage-specific debug options captured from the environment variable -/// "RUSTC_COVERAGE_DEBUG_OPTIONS", if set. Options can be set on the command line by, for example: -/// -/// $ RUSTC_COVERAGE_DEBUG_OPTIONS=counter-format=block,allow_unused_expressions=n cargo build +/// "RUSTC_COVERAGE_DEBUG_OPTIONS", if set. #[derive(Debug, Clone)] pub(crate) struct DebugOptions { pub allow_unused_expressions: bool, @@ -34,7 +142,7 @@ pub(crate) struct DebugOptions { } impl DebugOptions { - fn new() -> Self { + fn from_env() -> Self { let mut allow_unused_expressions = true; let mut counter_format = ExpressionFormat::default(); @@ -152,10 +260,11 @@ impl DebugCounters { } pub fn enable(&mut self) { + debug_assert!(!self.is_enabled()); self.some_counters.replace(FxHashMap::default()); } - pub fn is_enabled(&mut self) -> bool { + pub fn is_enabled(&self) -> bool { self.some_counters.is_some() } @@ -294,12 +403,13 @@ impl GraphvizData { } pub fn enable(&mut self) { + debug_assert!(!self.is_enabled()); self.some_bcb_to_coverage_spans_with_counters = Some(FxHashMap::default()); self.some_bcb_to_dependency_counters = Some(FxHashMap::default()); self.some_edge_to_counter = Some(FxHashMap::default()); } - pub fn is_enabled(&mut self) -> bool { + pub fn is_enabled(&self) -> bool { self.some_bcb_to_coverage_spans_with_counters.is_some() } @@ -399,11 +509,12 @@ impl UsedExpressions { } pub fn enable(&mut self) { + debug_assert!(!self.is_enabled()); self.some_used_expression_operands = Some(FxHashMap::default()); self.some_unused_expressions = Some(Vec::new()); } - pub fn is_enabled(&mut self) -> bool { + pub fn is_enabled(&self) -> bool { self.some_used_expression_operands.is_some() } @@ -416,7 +527,7 @@ impl UsedExpressions { } } - pub fn expression_is_used(&mut self, expression: &CoverageKind) -> bool { + pub fn expression_is_used(&self, expression: &CoverageKind) -> bool { if let Some(used_expression_operands) = self.some_used_expression_operands.as_ref() { used_expression_operands.contains_key(&expression.as_operand_id()) } else { diff --git a/compiler/rustc_mir/src/transform/coverage/graph.rs b/compiler/rustc_mir/src/transform/coverage/graph.rs index 84062541701..c2ed2cbb100 100644 --- a/compiler/rustc_mir/src/transform/coverage/graph.rs +++ b/compiler/rustc_mir/src/transform/coverage/graph.rs @@ -82,6 +82,8 @@ impl CoverageGraph { // each block terminator's `successors()`. Coverage spans must map to actual source code, // so compiler generated blocks and paths can be ignored. To that end, the CFG traversal // intentionally omits unwind paths. + // FIXME(#78544): MIR InstrumentCoverage: Improve coverage of `#[should_panic]` tests and + // `catch_unwind()` handlers. let mir_cfg_without_unwind = ShortCircuitPreorder::new(&mir_body, bcb_filtered_successors); let mut basic_blocks = Vec::new(); @@ -288,7 +290,8 @@ rustc_index::newtype_index! { /// * The BCB CFG ignores (trims) branches not relevant to coverage, such as unwind-related code, /// that is injected by the Rust compiler but has no physical source code to count. This also /// means a BasicBlock with a `Call` terminator can be merged into its primary successor target -/// block, in the same BCB. +/// block, in the same BCB. (But, note: Issue #78544: "MIR InstrumentCoverage: Improve coverage +/// of `#[should_panic]` tests and `catch_unwind()` handlers") /// * Some BasicBlock terminators support Rust-specific concerns--like borrow-checking--that are /// not relevant to coverage analysis. `FalseUnwind`, for example, can be treated the same as /// a `Goto`, and merged with its successor into the same BCB. @@ -329,7 +332,6 @@ impl BasicCoverageBlockData { &mir_body[self.last_bb()].terminator() } - #[inline(always)] pub fn set_counter( &mut self, counter_kind: CoverageKind, @@ -342,16 +344,15 @@ impl BasicCoverageBlockData { "attempt to add a `Counter` to a BCB target with existing incoming edge counters" ); let operand = counter_kind.as_operand_id(); - let expect_none = self.counter_kind.replace(counter_kind); - if expect_none.is_some() { - return Error::from_string(format!( + if let Some(replaced) = self.counter_kind.replace(counter_kind) { + Error::from_string(format!( "attempt to set a BasicCoverageBlock coverage counter more than once; \ {:?} already had counter {:?}", - self, - expect_none.unwrap(), - )); + self, replaced, + )) + } else { + Ok(operand) } - Ok(operand) } #[inline(always)] @@ -364,7 +365,6 @@ impl BasicCoverageBlockData { self.counter_kind.take() } - #[inline(always)] pub fn set_edge_counter_from( &mut self, from_bcb: BasicCoverageBlock, @@ -383,22 +383,22 @@ impl BasicCoverageBlockData { } } let operand = counter_kind.as_operand_id(); - let expect_none = self + if let Some(replaced) = self .edge_from_bcbs .get_or_insert_with(|| FxHashMap::default()) - .insert(from_bcb, counter_kind); - if expect_none.is_some() { - return Error::from_string(format!( + .insert(from_bcb, counter_kind) + { + Error::from_string(format!( "attempt to set an edge counter more than once; from_bcb: \ {:?} already had counter {:?}", - from_bcb, - expect_none.unwrap(), - )); + from_bcb, replaced, + )) + } else { + Ok(operand) } - Ok(operand) } - #[inline(always)] + #[inline] pub fn edge_counter_from(&self, from_bcb: BasicCoverageBlock) -> Option<&CoverageKind> { if let Some(edge_from_bcbs) = &self.edge_from_bcbs { edge_from_bcbs.get(&from_bcb) @@ -407,7 +407,7 @@ impl BasicCoverageBlockData { } } - #[inline(always)] + #[inline] pub fn take_edge_counters( &mut self, ) -> Option> { @@ -476,6 +476,9 @@ impl std::fmt::Debug for BcbBranch { } } +// Returns the `Terminator`s non-unwind successors. +// FIXME(#78544): MIR InstrumentCoverage: Improve coverage of `#[should_panic]` tests and +// `catch_unwind()` handlers. fn bcb_filtered_successors<'a, 'tcx>( body: &'tcx &'a mir::Body<'tcx>, term_kind: &'tcx TerminatorKind<'tcx>, @@ -495,6 +498,7 @@ fn bcb_filtered_successors<'a, 'tcx>( /// Maintains separate worklists for each loop in the BasicCoverageBlock CFG, plus one for the /// CoverageGraph outside all loops. This supports traversing the BCB CFG in a way that /// ensures a loop is completely traversed before processing Blocks after the end of the loop. +// FIXME(richkadel): Add unit tests for TraversalContext. #[derive(Debug)] pub(crate) struct TraversalContext { /// From one or more backedges returning to a loop header. @@ -644,7 +648,27 @@ fn find_loop_backedges( let num_bcbs = basic_coverage_blocks.num_nodes(); let mut backedges = IndexVec::from_elem_n(Vec::::new(), num_bcbs); - // Identify loops by their backedges + // Identify loops by their backedges. + // + // The computational complexity is bounded by: n(s) x d where `n` is the number of + // `BasicCoverageBlock` nodes (the simplified/reduced representation of the CFG derived from the + // MIR); `s` is the average number of successors per node (which is most likely less than 2, and + // independent of the size of the function, so it can be treated as a constant); + // and `d` is the average number of dominators per node. + // + // The average number of dominators depends on the size and complexity of the function, and + // nodes near the start of the function's control flow graph typically have less dominators + // than nodes near the end of the CFG. Without doing a detailed mathematical analysis, I + // think the resulting complexity has the characteristics of O(n log n). + // + // The overall complexity appears to be comparable to many other MIR transform algorithms, and I + // don't expect that this function is creating a performance hot spot, but if this becomes an + // issue, there may be ways to optimize the `is_dominated_by` algorithm (as indicated by an + // existing `FIXME` comment in that code), or possibly ways to optimize it's usage here, perhaps + // by keeping track of results for visited `BasicCoverageBlock`s if they can be used to short + // circuit downstream `is_dominated_by` checks. + // + // For now, that kind of optimization seems unnecessarily complicated. for (bcb, _) in basic_coverage_blocks.iter_enumerated() { for &successor in &basic_coverage_blocks.successors[bcb] { if basic_coverage_blocks.is_dominated_by(bcb, successor) { diff --git a/compiler/rustc_mir/src/transform/coverage/mod.rs b/compiler/rustc_mir/src/transform/coverage/mod.rs index c84ccf19213..c55349239b0 100644 --- a/compiler/rustc_mir/src/transform/coverage/mod.rs +++ b/compiler/rustc_mir/src/transform/coverage/mod.rs @@ -74,9 +74,6 @@ impl<'tcx> MirPass<'tcx> for InstrumentCoverage { trace!("InstrumentCoverage skipped for {:?} (not an FnLikeNode)", mir_source.def_id()); return; } - // FIXME(richkadel): By comparison, the MIR pass `ConstProp` includes associated constants, - // with functions, methods, and closures. I assume Miri is used for associated constants as - // well. If not, we may need to include them here too. trace!("InstrumentCoverage starting for {:?}", mir_source.def_id()); Instrumentor::new(&self.name(), tcx, mir_body).inject_counters(); @@ -121,7 +118,10 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { let mut graphviz_data = debug::GraphvizData::new(); let mut debug_used_expressions = debug::UsedExpressions::new(); - let dump_graphviz = tcx.sess.opts.debugging_opts.dump_mir_graphviz; + let dump_mir = pretty::dump_enabled(tcx, self.pass_name, def_id); + let dump_graphviz = dump_mir && tcx.sess.opts.debugging_opts.dump_mir_graphviz; + let dump_spanview = dump_mir && tcx.sess.opts.debugging_opts.dump_mir_spanview.is_some(); + if dump_graphviz { graphviz_data.enable(); self.coverage_counters.enable_debug(); @@ -139,7 +139,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { &self.basic_coverage_blocks, ); - if pretty::dump_enabled(tcx, self.pass_name, def_id) { + if dump_spanview { debug::dump_coverage_spanview( tcx, self.mir_body, @@ -174,6 +174,13 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { //////////////////////////////////////////////////// // Remove the counter or edge counter from of each `CoverageSpan`s associated // `BasicCoverageBlock`, and inject a `Coverage` statement into the MIR. + // + // `Coverage` statements injected from `CoverageSpan`s will include the code regions + // (source code start and end positions) to be counted by the associated counter. + // + // These `CoverageSpan`-associated counters are removed from their associated + // `BasicCoverageBlock`s so that the only remaining counters in the `CoverageGraph` + // are indirect counters (to be injected next, without associated code regions). self.inject_coverage_span_counters( coverage_spans, &mut graphviz_data, @@ -262,6 +269,8 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { bug!("Every BasicCoverageBlock should have a Counter or Expression"); }; graphviz_data.add_bcb_coverage_span_with_counter(bcb, &covspan, &counter_kind); + // FIXME(#78542): Can spans for `TerminatorKind::Goto` be improved to avoid special + // cases? let some_code_region = if self.is_code_region_redundant(bcb, span, body_span) { None } else { @@ -280,6 +289,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { /// /// If this method returns `true`, the counter (which other `Expressions` may depend on) is /// still injected, but without an associated code region. + // FIXME(#78542): Can spans for `TerminatorKind::Goto` be improved to avoid special cases? fn is_code_region_redundant( &self, bcb: BasicCoverageBlock, diff --git a/compiler/rustc_mir/src/transform/coverage/query.rs b/compiler/rustc_mir/src/transform/coverage/query.rs index 2fbbc9b675a..e86bb96d29c 100644 --- a/compiler/rustc_mir/src/transform/coverage/query.rs +++ b/compiler/rustc_mir/src/transform/coverage/query.rs @@ -1,5 +1,3 @@ -use super::counters; - use rustc_middle::mir::coverage::*; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{Coverage, CoverageInfo, Location}; @@ -44,11 +42,16 @@ struct CoverageVisitor { } impl CoverageVisitor { + /// Updates `num_counters` to the maximum encountered zero-based counter_id plus 1. Note the + /// final computed number of counters should be the number of all `CoverageKind::Counter` + /// statements in the MIR *plus one* for the implicit `ZERO` counter. #[inline(always)] fn update_num_counters(&mut self, counter_id: u32) { self.info.num_counters = std::cmp::max(self.info.num_counters, counter_id + 1); } + /// Computes an expression index for each expression ID, and updates `num_expressions` to the + /// maximum encountered index plus 1. #[inline(always)] fn update_num_expressions(&mut self, expression_id: u32) { let expression_index = u32::MAX - expression_id; @@ -59,10 +62,18 @@ impl CoverageVisitor { if operand_id >= self.info.num_counters { let operand_as_expression_index = u32::MAX - operand_id; if operand_as_expression_index >= self.info.num_expressions { - if operand_id <= counters::MAX_COUNTER_GUARD { - // Since the complete range of counter and expression IDs is not known here, the - // only way to determine if the ID is a counter ID or an expression ID is to - // assume a maximum possible counter ID value. + // The operand ID is outside the known range of counter IDs and also outside the + // known range of expression IDs. In either case, the result of a missing operand + // (if and when used in an expression) will be zero, so from a computation + // perspective, it doesn't matter whether it is interepretted as a counter or an + // expression. + // + // However, the `num_counters` and `num_expressions` query results are used to + // allocate arrays when generating the coverage map (during codegen), so choose + // the type that grows either `num_counters` or `num_expressions` the least. + if operand_id - self.info.num_counters + < operand_as_expression_index - self.info.num_expressions + { self.update_num_counters(operand_id) } else { self.update_num_expressions(operand_id) @@ -100,7 +111,8 @@ fn coverageinfo_from_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> CoverageInfo let mir_body = tcx.optimized_mir(def_id); let mut coverage_visitor = CoverageVisitor { - info: CoverageInfo { num_counters: 0, num_expressions: 0 }, + // num_counters always has at least the `ZERO` counter. + info: CoverageInfo { num_counters: 1, num_expressions: 0 }, add_missing_operands: false, }; diff --git a/compiler/rustc_mir/src/transform/coverage/spans.rs b/compiler/rustc_mir/src/transform/coverage/spans.rs index 8549ac0e4af..cda4fc12544 100644 --- a/compiler/rustc_mir/src/transform/coverage/spans.rs +++ b/compiler/rustc_mir/src/transform/coverage/spans.rs @@ -656,7 +656,9 @@ fn filtered_statement_span(statement: &'a Statement<'tcx>, body_span: Span) -> O // Ignore `Nop`s | StatementKind::Nop => None, - // FIXME(richkadel): Look into a possible issue assigning the span to a + // FIXME(#78546): MIR InstrumentCoverage - Can the source_info.span for `FakeRead` + // statements be more consistent? + // // FakeReadCause::ForGuardBinding, in this example: // match somenum { // x if x < 1 => { ... } @@ -669,15 +671,7 @@ fn filtered_statement_span(statement: &'a Statement<'tcx>, body_span: Span) -> O // _4 = &_1; (at the span for the first `x`) // and `_1` is the `Place` for `somenum`. // - // The arm code BasicBlock already has its own assignment for `x` itself, `_3 = 1`, and I've - // decided it's reasonable for that span (even though outside the arm code) to be part of - // the counted coverage of the arm code execution, but I can't justify including the literal - // `1` in the arm code. I'm pretty sure that, if the `FakeRead(ForGuardBinding)` has a - // purpose in codegen, it's probably in the right BasicBlock, but if so, the `Statement`s - // `source_info.span` can't be right. - // - // Consider correcting the span assignment, assuming there is a better solution, and see if - // the following pattern can be removed here: + // If and when the Issue is resolved, remove this special case match pattern: StatementKind::FakeRead(cause, _) if cause == FakeReadCause::ForGuardBinding => None, // Retain spans from all other statements @@ -710,13 +704,7 @@ fn filtered_terminator_span(terminator: &'a Terminator<'tcx>, body_span: Span) - // `FalseEdge`. | TerminatorKind::FalseEdge { .. } => None, - // FIXME(richkadel): Note that `Goto` was initially filtered out (by returning `None`, as - // with the `TerminatorKind`s above) because its `Span` was way to broad to be beneficial, - // and, at the time, `Goto` didn't seem to provide any additional contributions to the - // coverage analysis. Upon further review, `Goto` terminated blocks do appear to benefit - // the coverage analysis, and the BCB CFG. To overcome the issues with the `Spans`, the - // coverage algorithms--and the final coverage map generation--include some exceptional - // behaviors. + // FIXME(#78542): Can spans for `TerminatorKind::Goto` be improved to avoid special cases? // // `Goto`s are often the targets of `SwitchInt` branches, and certain important // optimizations to replace some `Counter`s with `Expression`s require a separate @@ -750,7 +738,7 @@ fn filtered_terminator_span(terminator: &'a Terminator<'tcx>, body_span: Span) - } } -#[inline(always)] +#[inline] fn function_source_span(span: Span, body_span: Span) -> Span { let span = original_sp(span, body_span).with_ctxt(SyntaxContext::root()); if body_span.contains(span) { span } else { body_span } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 4c00361dd31..ceed730e25b 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -887,12 +887,15 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, dump_mir_exclude_pass_number: bool = (false, parse_bool, [UNTRACKED], "exclude the pass number when dumping MIR (used in tests) (default: no)"), dump_mir_graphviz: bool = (false, parse_bool, [UNTRACKED], - "in addition to `.mir` files, create graphviz `.dot` files (default: no)"), + "in addition to `.mir` files, create graphviz `.dot` files (and with \ + `-Z instrument-coverage`, also create a `.dot` file for the MIR-derived \ + coverage graph) (default: no)"), dump_mir_spanview: Option = (None, parse_mir_spanview, [UNTRACKED], "in addition to `.mir` files, create `.html` files to view spans for \ all `statement`s (including terminators), only `terminator` spans, or \ computed `block` spans (one span encompassing a block's terminator and \ - all statements)."), + all statements). If `-Z instrument-coverage` is also enabled, create \ + an additional `.html` file showing the computed coverage spans."), emit_future_incompat_report: bool = (false, parse_bool, [UNTRACKED], "emits a future-incompatibility report for lints (RFC 2834)"), emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED], diff --git a/src/test/run-make-fulldeps/coverage-spanview-base/Makefile b/src/test/run-make-fulldeps/coverage-spanview-base/Makefile index ecb5275e716..ec93ca4725e 100644 --- a/src/test/run-make-fulldeps/coverage-spanview-base/Makefile +++ b/src/test/run-make-fulldeps/coverage-spanview-base/Makefile @@ -26,6 +26,7 @@ endif -Zinstrument-coverage \ -Clink-dead-code=$(LINK_DEAD_CODE) \ -Zdump-mir=InstrumentCoverage \ + -Zdump-mir-spanview \ -Zdump-mir-dir="$(TMPDIR)"/mir_dump.$@ for path in "$(TMPDIR)"/mir_dump.$@/*; do \ diff --git a/src/test/run-make-fulldeps/coverage/coverage_tools.mk b/src/test/run-make-fulldeps/coverage/coverage_tools.mk index ad5f465c54f..17f7696a8cf 100644 --- a/src/test/run-make-fulldeps/coverage/coverage_tools.mk +++ b/src/test/run-make-fulldeps/coverage/coverage_tools.mk @@ -37,3 +37,8 @@ endif # tests can be simplified to always test with `-C link-dead-code`. UNAME = $(shell uname) + +# FIXME(richkadel): Can any of the features tested by `run-make-fulldeps/coverage-*` tests be tested +# just as completely by more focused unit tests of the code logic itself, to reduce the number of +# test result files generated and maintained, and to help identify specific test failures and root +# causes more easily? -- cgit 1.4.1-3-g733a5