coverage: Store BCB node IDs in mappings, and resolve them in codegen
Even though the coverage graph itself is no longer available during codegen, its nodes can still be used as opaque IDs.
This commit is contained in:
parent
59588250ad
commit
ee7dc06cf1
12 changed files with 91 additions and 103 deletions
|
@ -133,7 +133,7 @@ pub(super) struct CoverageCounters {
|
|||
next_counter_id: CounterId,
|
||||
|
||||
/// Coverage counters/expressions that are associated with individual BCBs.
|
||||
node_counters: IndexVec<BasicCoverageBlock, Option<CovTerm>>,
|
||||
pub(crate) node_counters: IndexVec<BasicCoverageBlock, Option<CovTerm>>,
|
||||
|
||||
/// Table of expression data, associating each expression ID with its
|
||||
/// corresponding operator (+ or -) and its LHS/RHS operands.
|
||||
|
@ -203,10 +203,6 @@ impl CoverageCounters {
|
|||
counter
|
||||
}
|
||||
|
||||
pub(super) fn term_for_bcb(&self, bcb: BasicCoverageBlock) -> Option<CovTerm> {
|
||||
self.node_counters[bcb]
|
||||
}
|
||||
|
||||
/// Returns an iterator over all the nodes in the coverage graph that
|
||||
/// should have a counter-increment statement injected into MIR, along with
|
||||
/// each site's corresponding counter ID.
|
||||
|
|
|
@ -8,6 +8,7 @@ use rustc_data_structures::graph::dominators::Dominators;
|
|||
use rustc_data_structures::graph::{self, DirectedGraph, StartNode};
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_index::bit_set::DenseBitSet;
|
||||
pub(crate) use rustc_middle::mir::coverage::{BasicCoverageBlock, START_BCB};
|
||||
use rustc_middle::mir::{self, BasicBlock, Terminator, TerminatorKind};
|
||||
use tracing::debug;
|
||||
|
||||
|
@ -269,15 +270,6 @@ impl graph::Predecessors for CoverageGraph {
|
|||
}
|
||||
}
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
/// A node in the control-flow graph of CoverageGraph.
|
||||
#[orderable]
|
||||
#[debug_format = "bcb{}"]
|
||||
pub(crate) struct BasicCoverageBlock {
|
||||
const START_BCB = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// `BasicCoverageBlockData` holds the data indexed by a `BasicCoverageBlock`.
|
||||
///
|
||||
/// A `BasicCoverageBlock` (BCB) represents the maximal-length sequence of MIR `BasicBlock`s without
|
||||
|
|
|
@ -95,12 +95,13 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir:
|
|||
|
||||
let coverage_counters = counters::make_bcb_counters(&graph, &bcbs_with_counter_mappings);
|
||||
|
||||
let mappings = create_mappings(&extracted_mappings, &coverage_counters);
|
||||
let mappings = create_mappings(&extracted_mappings);
|
||||
if mappings.is_empty() {
|
||||
// No spans could be converted into valid mappings, so skip this function.
|
||||
debug!("no spans could be converted into valid mappings; skipping");
|
||||
return;
|
||||
}
|
||||
let term_for_bcb = coverage_counters.node_counters.clone();
|
||||
|
||||
inject_coverage_statements(mir_body, &graph, &extracted_mappings, &coverage_counters);
|
||||
|
||||
|
@ -116,26 +117,24 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir:
|
|||
mir_body.function_coverage_info = Some(Box::new(FunctionCoverageInfo {
|
||||
function_source_hash: hir_info.function_source_hash,
|
||||
body_span: hir_info.body_span,
|
||||
|
||||
num_counters: coverage_counters.num_counters(),
|
||||
mcdc_bitmap_bits: extracted_mappings.mcdc_bitmap_bits,
|
||||
expressions: coverage_counters.into_expressions(),
|
||||
|
||||
mappings,
|
||||
term_for_bcb,
|
||||
|
||||
mcdc_bitmap_bits: extracted_mappings.mcdc_bitmap_bits,
|
||||
mcdc_num_condition_bitmaps,
|
||||
}));
|
||||
}
|
||||
|
||||
/// For each coverage span extracted from MIR, create a corresponding
|
||||
/// mapping.
|
||||
/// For each coverage span extracted from MIR, create a corresponding mapping.
|
||||
///
|
||||
/// Precondition: All BCBs corresponding to those spans have been given
|
||||
/// coverage counters.
|
||||
fn create_mappings(
|
||||
extracted_mappings: &ExtractedMappings,
|
||||
coverage_counters: &CoverageCounters,
|
||||
) -> Vec<Mapping> {
|
||||
let term_for_bcb =
|
||||
|bcb| coverage_counters.term_for_bcb(bcb).expect("all BCBs with spans were given counters");
|
||||
|
||||
/// FIXME(Zalathar): This used to be where BCBs in the extracted mappings were
|
||||
/// resolved to a `CovTerm`. But that is now handled elsewhere, so this
|
||||
/// function can potentially be simplified even further.
|
||||
fn create_mappings(extracted_mappings: &ExtractedMappings) -> Vec<Mapping> {
|
||||
// Fully destructure the mappings struct to make sure we don't miss any kinds.
|
||||
let ExtractedMappings {
|
||||
num_bcbs: _,
|
||||
|
@ -150,23 +149,18 @@ fn create_mappings(
|
|||
mappings.extend(code_mappings.iter().map(
|
||||
// Ordinary code mappings are the simplest kind.
|
||||
|&mappings::CodeMapping { span, bcb }| {
|
||||
let kind = MappingKind::Code(term_for_bcb(bcb));
|
||||
let kind = MappingKind::Code { bcb };
|
||||
Mapping { kind, span }
|
||||
},
|
||||
));
|
||||
|
||||
mappings.extend(branch_pairs.iter().map(
|
||||
|&mappings::BranchPair { span, true_bcb, false_bcb }| {
|
||||
let true_term = term_for_bcb(true_bcb);
|
||||
let false_term = term_for_bcb(false_bcb);
|
||||
let kind = MappingKind::Branch { true_term, false_term };
|
||||
let kind = MappingKind::Branch { true_bcb, false_bcb };
|
||||
Mapping { kind, span }
|
||||
},
|
||||
));
|
||||
|
||||
let term_for_bcb =
|
||||
|bcb| coverage_counters.term_for_bcb(bcb).expect("all BCBs with spans were given counters");
|
||||
|
||||
// MCDC branch mappings are appended with their decisions in case decisions were ignored.
|
||||
mappings.extend(mcdc_degraded_branches.iter().map(
|
||||
|&mappings::MCDCBranch {
|
||||
|
@ -176,11 +170,7 @@ fn create_mappings(
|
|||
condition_info: _,
|
||||
true_index: _,
|
||||
false_index: _,
|
||||
}| {
|
||||
let true_term = term_for_bcb(true_bcb);
|
||||
let false_term = term_for_bcb(false_bcb);
|
||||
Mapping { kind: MappingKind::Branch { true_term, false_term }, span }
|
||||
},
|
||||
}| { Mapping { kind: MappingKind::Branch { true_bcb, false_bcb }, span } },
|
||||
));
|
||||
|
||||
for (decision, branches) in mcdc_mappings {
|
||||
|
@ -201,12 +191,10 @@ fn create_mappings(
|
|||
true_index: _,
|
||||
false_index: _,
|
||||
}| {
|
||||
let true_term = term_for_bcb(true_bcb);
|
||||
let false_term = term_for_bcb(false_bcb);
|
||||
Mapping {
|
||||
kind: MappingKind::MCDCBranch {
|
||||
true_term,
|
||||
false_term,
|
||||
true_bcb,
|
||||
false_bcb,
|
||||
mcdc_params: condition_info,
|
||||
},
|
||||
span,
|
||||
|
|
|
@ -101,7 +101,9 @@ fn coverage_ids_info<'tcx>(
|
|||
// to any particular point in the control-flow graph.
|
||||
// (Keep this in sync with the injection of `ExpressionUsed`
|
||||
// statements in the `InstrumentCoverage` MIR pass.)
|
||||
if let MappingKind::Code(CovTerm::Expression(id)) = mapping.kind {
|
||||
if let MappingKind::Code { bcb } = mapping.kind
|
||||
&& let Some(CovTerm::Expression(id)) = fn_cov_info.term_for_bcb[bcb]
|
||||
{
|
||||
expressions_seen.remove(id);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue