Rollup merge of #79818 - richkadel:llvm-coverage-counters-2.1.0, r=tmandry
Fixes to Rust coverage Fixes: #79725 Some macros can create a situation where `fn_sig_span` and `body_span` map to different files. New documentation on coverage tests incorrectly assumed multiple test binaries could just be listed at the end of the `llvm-cov` command, but it turns out each binary needs a `--object` prefix. This PR fixes the bug and updates the documentation to correct that issue. It also fixes a few other minor issues in internal implementation comments, and adds documentation on getting coverage results for doc tests.
This commit is contained in:
commit
3b49a46c6b
10 changed files with 160 additions and 59 deletions
|
@ -33,7 +33,7 @@ impl CoverageGraph {
|
|||
// 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
|
||||
// BCB last_bb should be in its own unique BCB. Therefore, collecting the BCBs using
|
||||
// `bb_to_bcb` should work without requiring a deduplication step.
|
||||
|
||||
let successors = IndexVec::from_fn_n(
|
||||
|
@ -283,7 +283,9 @@ rustc_index::newtype_index! {
|
|||
}
|
||||
}
|
||||
|
||||
/// A BasicCoverageBlockData (BCB) represents the maximal-length sequence of MIR BasicBlocks without
|
||||
/// `BasicCoverageBlockData` holds the data indexed by a `BasicCoverageBlock`.
|
||||
///
|
||||
/// A `BasicCoverageBlock` (BCB) represents the maximal-length sequence of MIR `BasicBlock`s without
|
||||
/// conditional branches, and form a new, simplified, coverage-specific Control Flow Graph, without
|
||||
/// altering the original MIR CFG.
|
||||
///
|
||||
|
|
|
@ -88,6 +88,7 @@ struct Instrumentor<'a, 'tcx> {
|
|||
pass_name: &'a str,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
mir_body: &'a mut mir::Body<'tcx>,
|
||||
source_file: Lrc<SourceFile>,
|
||||
fn_sig_span: Span,
|
||||
body_span: Span,
|
||||
basic_coverage_blocks: CoverageGraph,
|
||||
|
@ -96,9 +97,13 @@ struct Instrumentor<'a, 'tcx> {
|
|||
|
||||
impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
|
||||
fn new(pass_name: &'a str, tcx: TyCtxt<'tcx>, mir_body: &'a mut mir::Body<'tcx>) -> Self {
|
||||
let source_map = tcx.sess.source_map();
|
||||
let (some_fn_sig, hir_body) = fn_sig_and_body(tcx, mir_body.source.def_id());
|
||||
let body_span = hir_body.value.span;
|
||||
let fn_sig_span = match some_fn_sig {
|
||||
let source_file = source_map.lookup_source_file(body_span.lo());
|
||||
let fn_sig_span = match some_fn_sig.filter(|fn_sig| {
|
||||
Lrc::ptr_eq(&source_file, &source_map.lookup_source_file(fn_sig.span.hi()))
|
||||
}) {
|
||||
Some(fn_sig) => fn_sig.span.with_hi(body_span.lo()),
|
||||
None => body_span.shrink_to_lo(),
|
||||
};
|
||||
|
@ -108,6 +113,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
|
|||
pass_name,
|
||||
tcx,
|
||||
mir_body,
|
||||
source_file,
|
||||
fn_sig_span,
|
||||
body_span,
|
||||
basic_coverage_blocks,
|
||||
|
@ -268,8 +274,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
|
|||
let tcx = self.tcx;
|
||||
let source_map = tcx.sess.source_map();
|
||||
let body_span = self.body_span;
|
||||
let source_file = source_map.lookup_source_file(body_span.lo());
|
||||
let file_name = Symbol::intern(&source_file.name.to_string());
|
||||
let file_name = Symbol::intern(&self.source_file.name.to_string());
|
||||
|
||||
let mut bcb_counters = IndexVec::from_elem_n(None, self.basic_coverage_blocks.num_nodes());
|
||||
for covspan in coverage_spans {
|
||||
|
@ -285,11 +290,20 @@ 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);
|
||||
|
||||
debug!(
|
||||
"Calling make_code_region(file_name={}, source_file={:?}, span={}, body_span={})",
|
||||
file_name,
|
||||
self.source_file,
|
||||
source_map.span_to_string(span),
|
||||
source_map.span_to_string(body_span)
|
||||
);
|
||||
|
||||
inject_statement(
|
||||
self.mir_body,
|
||||
counter_kind,
|
||||
self.bcb_last_bb(bcb),
|
||||
Some(make_code_region(file_name, &source_file, span, body_span)),
|
||||
Some(make_code_region(file_name, &self.source_file, span, body_span)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -217,6 +217,27 @@ pub struct CoverageSpans<'a, 'tcx> {
|
|||
}
|
||||
|
||||
impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
|
||||
/// Generate a minimal set of `CoverageSpan`s, each representing a contiguous code region to be
|
||||
/// counted.
|
||||
///
|
||||
/// The basic steps are:
|
||||
///
|
||||
/// 1. Extract an initial set of spans from the `Statement`s and `Terminator`s of each
|
||||
/// `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).
|
||||
/// 3. Traverse the spans in sorted order to identify spans that can be dropped (for instance,
|
||||
/// if another span or spans are already counting the same code region), or should be merged
|
||||
/// into a broader combined span (because it represents a contiguous, non-branching, and
|
||||
/// uninterrupted region of source code).
|
||||
///
|
||||
/// Closures are exposed in their enclosing functions as `Assign` `Rvalue`s, and since
|
||||
/// closures have their own MIR, their `Span` in their enclosing function should be left
|
||||
/// "uncovered".
|
||||
///
|
||||
/// Note the resulting vector of `CoverageSpan`s may not be fully sorted (and does not need
|
||||
/// to be).
|
||||
pub(super) fn generate_coverage_spans(
|
||||
mir_body: &'a mir::Body<'tcx>,
|
||||
fn_sig_span: Span,
|
||||
|
@ -247,27 +268,6 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
|
|||
coverage_spans.to_refined_spans()
|
||||
}
|
||||
|
||||
/// Generate a minimal set of `CoverageSpan`s, each representing a contiguous code region to be
|
||||
/// counted.
|
||||
///
|
||||
/// The basic steps are:
|
||||
///
|
||||
/// 1. Extract an initial set of spans from the `Statement`s and `Terminator`s of each
|
||||
/// `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).
|
||||
/// 3. Traverse the spans in sorted order to identify spans that can be dropped (for instance,
|
||||
/// if another span or spans are already counting the same code region), or should be merged
|
||||
/// into a broader combined span (because it represents a contiguous, non-branching, and
|
||||
/// uninterrupted region of source code).
|
||||
///
|
||||
/// Closures are exposed in their enclosing functions as `Assign` `Rvalue`s, and since
|
||||
/// closures have their own MIR, their `Span` in their enclosing function should be left
|
||||
/// "uncovered".
|
||||
///
|
||||
/// Note the resulting vector of `CoverageSpan`s does may not be fully sorted (and does not need
|
||||
/// to be).
|
||||
fn mir_to_initial_sorted_coverage_spans(&self) -> Vec<CoverageSpan> {
|
||||
let mut initial_spans = Vec::<CoverageSpan>::with_capacity(self.mir_body.num_nodes() * 2);
|
||||
for (bcb, bcb_data) in self.basic_coverage_blocks.iter_enumerated() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue