coverage: Give the instrumentor its own counter type, separate from MIR
This splits off `BcbCounter` from MIR's `CoverageKind`, allowing the two types to evolve in different directions as necessary.
This commit is contained in:
parent
629437eec7
commit
fbab055e77
5 changed files with 129 additions and 85 deletions
|
@ -96,21 +96,6 @@ pub enum CoverageKind {
|
||||||
Unreachable,
|
Unreachable,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CoverageKind {
|
|
||||||
pub fn as_operand(&self) -> Operand {
|
|
||||||
use CoverageKind::*;
|
|
||||||
match *self {
|
|
||||||
Counter { id, .. } => Operand::Counter(id),
|
|
||||||
Expression { id, .. } => Operand::Expression(id),
|
|
||||||
Unreachable => bug!("Unreachable coverage cannot be part of an expression"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_expression(&self) -> bool {
|
|
||||||
matches!(self, Self::Expression { .. })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Debug for CoverageKind {
|
impl Debug for CoverageKind {
|
||||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
||||||
use CoverageKind::*;
|
use CoverageKind::*;
|
||||||
|
|
|
@ -14,6 +14,48 @@ use rustc_index::bit_set::BitSet;
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
use rustc_middle::mir::coverage::*;
|
use rustc_middle::mir::coverage::*;
|
||||||
|
|
||||||
|
use std::fmt::{self, Debug};
|
||||||
|
|
||||||
|
/// The coverage counter or counter expression associated with a particular
|
||||||
|
/// BCB node or BCB edge.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub(super) enum BcbCounter {
|
||||||
|
Counter { function_source_hash: u64, id: CounterId },
|
||||||
|
Expression { id: ExpressionId, lhs: Operand, op: Op, rhs: Operand },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BcbCounter {
|
||||||
|
fn is_expression(&self) -> bool {
|
||||||
|
matches!(self, Self::Expression { .. })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn as_operand(&self) -> Operand {
|
||||||
|
match *self {
|
||||||
|
BcbCounter::Counter { id, .. } => Operand::Counter(id),
|
||||||
|
BcbCounter::Expression { id, .. } => Operand::Expression(id),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for BcbCounter {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Counter { id, .. } => write!(fmt, "Counter({:?})", id.index()),
|
||||||
|
Self::Expression { id, lhs, op, rhs } => write!(
|
||||||
|
fmt,
|
||||||
|
"Expression({:?}) = {:?} {} {:?}",
|
||||||
|
id.index(),
|
||||||
|
lhs,
|
||||||
|
match op {
|
||||||
|
Op::Add => "+",
|
||||||
|
Op::Subtract => "-",
|
||||||
|
},
|
||||||
|
rhs,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Generates and stores coverage counter and coverage expression information
|
/// Generates and stores coverage counter and coverage expression information
|
||||||
/// associated with nodes/edges in the BCB graph.
|
/// associated with nodes/edges in the BCB graph.
|
||||||
pub(super) struct CoverageCounters {
|
pub(super) struct CoverageCounters {
|
||||||
|
@ -22,18 +64,18 @@ pub(super) struct CoverageCounters {
|
||||||
next_expression_id: ExpressionId,
|
next_expression_id: ExpressionId,
|
||||||
|
|
||||||
/// Coverage counters/expressions that are associated with individual BCBs.
|
/// Coverage counters/expressions that are associated with individual BCBs.
|
||||||
bcb_counters: IndexVec<BasicCoverageBlock, Option<CoverageKind>>,
|
bcb_counters: IndexVec<BasicCoverageBlock, Option<BcbCounter>>,
|
||||||
/// Coverage counters/expressions that are associated with the control-flow
|
/// Coverage counters/expressions that are associated with the control-flow
|
||||||
/// edge between two BCBs.
|
/// edge between two BCBs.
|
||||||
bcb_edge_counters: FxHashMap<(BasicCoverageBlock, BasicCoverageBlock), CoverageKind>,
|
bcb_edge_counters: FxHashMap<(BasicCoverageBlock, BasicCoverageBlock), BcbCounter>,
|
||||||
/// Tracks which BCBs have a counter associated with some incoming edge.
|
/// Tracks which BCBs have a counter associated with some incoming edge.
|
||||||
/// Only used by debug assertions, to verify that BCBs with incoming edge
|
/// Only used by debug assertions, to verify that BCBs with incoming edge
|
||||||
/// counters do not have their own physical counters (expressions are allowed).
|
/// counters do not have their own physical counters (expressions are allowed).
|
||||||
bcb_has_incoming_edge_counters: BitSet<BasicCoverageBlock>,
|
bcb_has_incoming_edge_counters: BitSet<BasicCoverageBlock>,
|
||||||
/// Expression nodes that are not directly associated with any particular
|
/// Expression nodes that are not directly associated with any particular
|
||||||
/// BCB/edge, but are needed as operands to more complex expressions.
|
/// BCB/edge, but are needed as operands to more complex expressions.
|
||||||
/// These are always `CoverageKind::Expression`.
|
/// These are always [`BcbCounter::Expression`].
|
||||||
pub(super) intermediate_expressions: Vec<CoverageKind>,
|
pub(super) intermediate_expressions: Vec<BcbCounter>,
|
||||||
|
|
||||||
pub debug_counters: DebugCounters,
|
pub debug_counters: DebugCounters,
|
||||||
}
|
}
|
||||||
|
@ -57,12 +99,12 @@ impl CoverageCounters {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Activate the `DebugCounters` data structures, to provide additional debug formatting
|
/// Activate the `DebugCounters` data structures, to provide additional debug formatting
|
||||||
/// features when formatting `CoverageKind` (counter) values.
|
/// features when formatting [`BcbCounter`] (counter) values.
|
||||||
pub fn enable_debug(&mut self) {
|
pub fn enable_debug(&mut self) {
|
||||||
self.debug_counters.enable();
|
self.debug_counters.enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes `CoverageKind` `Counter`s and `Expressions` for the `BasicCoverageBlock`s directly or
|
/// Makes [`BcbCounter`] `Counter`s and `Expressions` for the `BasicCoverageBlock`s directly or
|
||||||
/// indirectly associated with `CoverageSpans`, and accumulates additional `Expression`s
|
/// indirectly associated with `CoverageSpans`, and accumulates additional `Expression`s
|
||||||
/// representing intermediate values.
|
/// representing intermediate values.
|
||||||
pub fn make_bcb_counters(
|
pub fn make_bcb_counters(
|
||||||
|
@ -73,11 +115,11 @@ impl CoverageCounters {
|
||||||
MakeBcbCounters::new(self, basic_coverage_blocks).make_bcb_counters(coverage_spans)
|
MakeBcbCounters::new(self, basic_coverage_blocks).make_bcb_counters(coverage_spans)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_counter<F>(&mut self, debug_block_label_fn: F) -> CoverageKind
|
fn make_counter<F>(&mut self, debug_block_label_fn: F) -> BcbCounter
|
||||||
where
|
where
|
||||||
F: Fn() -> Option<String>,
|
F: Fn() -> Option<String>,
|
||||||
{
|
{
|
||||||
let counter = CoverageKind::Counter {
|
let counter = BcbCounter::Counter {
|
||||||
function_source_hash: self.function_source_hash,
|
function_source_hash: self.function_source_hash,
|
||||||
id: self.next_counter(),
|
id: self.next_counter(),
|
||||||
};
|
};
|
||||||
|
@ -93,19 +135,19 @@ impl CoverageCounters {
|
||||||
op: Op,
|
op: Op,
|
||||||
rhs: Operand,
|
rhs: Operand,
|
||||||
debug_block_label_fn: F,
|
debug_block_label_fn: F,
|
||||||
) -> CoverageKind
|
) -> BcbCounter
|
||||||
where
|
where
|
||||||
F: Fn() -> Option<String>,
|
F: Fn() -> Option<String>,
|
||||||
{
|
{
|
||||||
let id = self.next_expression();
|
let id = self.next_expression();
|
||||||
let expression = CoverageKind::Expression { id, lhs, op, rhs };
|
let expression = BcbCounter::Expression { id, lhs, op, rhs };
|
||||||
if self.debug_counters.is_enabled() {
|
if self.debug_counters.is_enabled() {
|
||||||
self.debug_counters.add_counter(&expression, (debug_block_label_fn)());
|
self.debug_counters.add_counter(&expression, (debug_block_label_fn)());
|
||||||
}
|
}
|
||||||
expression
|
expression
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_identity_counter(&mut self, counter_operand: Operand) -> CoverageKind {
|
pub fn make_identity_counter(&mut self, counter_operand: Operand) -> BcbCounter {
|
||||||
let some_debug_block_label = if self.debug_counters.is_enabled() {
|
let some_debug_block_label = if self.debug_counters.is_enabled() {
|
||||||
self.debug_counters.some_block_label(counter_operand).cloned()
|
self.debug_counters.some_block_label(counter_operand).cloned()
|
||||||
} else {
|
} else {
|
||||||
|
@ -134,7 +176,7 @@ impl CoverageCounters {
|
||||||
fn set_bcb_counter(
|
fn set_bcb_counter(
|
||||||
&mut self,
|
&mut self,
|
||||||
bcb: BasicCoverageBlock,
|
bcb: BasicCoverageBlock,
|
||||||
counter_kind: CoverageKind,
|
counter_kind: BcbCounter,
|
||||||
) -> Result<Operand, Error> {
|
) -> Result<Operand, Error> {
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
// If the BCB has an edge counter (to be injected into a new `BasicBlock`), it can also
|
// If the BCB has an edge counter (to be injected into a new `BasicBlock`), it can also
|
||||||
|
@ -158,7 +200,7 @@ impl CoverageCounters {
|
||||||
&mut self,
|
&mut self,
|
||||||
from_bcb: BasicCoverageBlock,
|
from_bcb: BasicCoverageBlock,
|
||||||
to_bcb: BasicCoverageBlock,
|
to_bcb: BasicCoverageBlock,
|
||||||
counter_kind: CoverageKind,
|
counter_kind: BcbCounter,
|
||||||
) -> Result<Operand, Error> {
|
) -> Result<Operand, Error> {
|
||||||
if level_enabled!(tracing::Level::DEBUG) {
|
if level_enabled!(tracing::Level::DEBUG) {
|
||||||
// If the BCB has an edge counter (to be injected into a new `BasicBlock`), it can also
|
// If the BCB has an edge counter (to be injected into a new `BasicBlock`), it can also
|
||||||
|
@ -183,17 +225,17 @@ impl CoverageCounters {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn bcb_counter(&self, bcb: BasicCoverageBlock) -> Option<&CoverageKind> {
|
pub(super) fn bcb_counter(&self, bcb: BasicCoverageBlock) -> Option<&BcbCounter> {
|
||||||
self.bcb_counters[bcb].as_ref()
|
self.bcb_counters[bcb].as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn take_bcb_counter(&mut self, bcb: BasicCoverageBlock) -> Option<CoverageKind> {
|
pub(super) fn take_bcb_counter(&mut self, bcb: BasicCoverageBlock) -> Option<BcbCounter> {
|
||||||
self.bcb_counters[bcb].take()
|
self.bcb_counters[bcb].take()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn drain_bcb_counters(
|
pub(super) fn drain_bcb_counters(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> impl Iterator<Item = (BasicCoverageBlock, CoverageKind)> + '_ {
|
) -> impl Iterator<Item = (BasicCoverageBlock, BcbCounter)> + '_ {
|
||||||
self.bcb_counters
|
self.bcb_counters
|
||||||
.iter_enumerated_mut()
|
.iter_enumerated_mut()
|
||||||
.filter_map(|(bcb, counter)| Some((bcb, counter.take()?)))
|
.filter_map(|(bcb, counter)| Some((bcb, counter.take()?)))
|
||||||
|
@ -201,7 +243,7 @@ impl CoverageCounters {
|
||||||
|
|
||||||
pub(super) fn drain_bcb_edge_counters(
|
pub(super) fn drain_bcb_edge_counters(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> impl Iterator<Item = ((BasicCoverageBlock, BasicCoverageBlock), CoverageKind)> + '_ {
|
) -> impl Iterator<Item = ((BasicCoverageBlock, BasicCoverageBlock), BcbCounter)> + '_ {
|
||||||
self.bcb_edge_counters.drain()
|
self.bcb_edge_counters.drain()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -653,7 +695,7 @@ impl<'a> MakeBcbCounters<'a> {
|
||||||
self.branch_counter(branch).is_none()
|
self.branch_counter(branch).is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn branch_counter(&self, branch: &BcbBranch) -> Option<&CoverageKind> {
|
fn branch_counter(&self, branch: &BcbBranch) -> Option<&BcbCounter> {
|
||||||
let to_bcb = branch.target_bcb;
|
let to_bcb = branch.target_bcb;
|
||||||
if let Some(from_bcb) = branch.edge_from_bcb {
|
if let Some(from_bcb) = branch.edge_from_bcb {
|
||||||
self.coverage_counters.bcb_edge_counters.get(&(from_bcb, to_bcb))
|
self.coverage_counters.bcb_edge_counters.get(&(from_bcb, to_bcb))
|
||||||
|
@ -675,7 +717,7 @@ impl<'a> MakeBcbCounters<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn format_counter(&self, counter_kind: &CoverageKind) -> String {
|
fn format_counter(&self, counter_kind: &BcbCounter) -> String {
|
||||||
self.coverage_counters.debug_counters.format_counter(counter_kind)
|
self.coverage_counters.debug_counters.format_counter(counter_kind)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@
|
||||||
//! recursively, generating labels with nested operations, enclosed in parentheses
|
//! recursively, generating labels with nested operations, enclosed in parentheses
|
||||||
//! (for example: `bcb2 + (bcb0 - bcb1)`).
|
//! (for example: `bcb2 + (bcb0 - bcb1)`).
|
||||||
|
|
||||||
use super::counters::CoverageCounters;
|
use super::counters::{BcbCounter, CoverageCounters};
|
||||||
use super::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph};
|
use super::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph};
|
||||||
use super::spans::CoverageSpan;
|
use super::spans::CoverageSpan;
|
||||||
|
|
||||||
|
@ -247,11 +247,11 @@ impl Default for ExpressionFormat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If enabled, this struct maintains a map from `CoverageKind` IDs (as `Operand`) to
|
/// If enabled, this struct maintains a map from `BcbCounter` IDs (as `Operand`) to
|
||||||
/// the `CoverageKind` data and optional label (normally, the counter's associated
|
/// the `BcbCounter` data and optional label (normally, the counter's associated
|
||||||
/// `BasicCoverageBlock` format string, if any).
|
/// `BasicCoverageBlock` format string, if any).
|
||||||
///
|
///
|
||||||
/// Use `format_counter` to convert one of these `CoverageKind` counters to a debug output string,
|
/// Use `format_counter` to convert one of these `BcbCounter` counters to a debug output string,
|
||||||
/// as directed by the `DebugOptions`. This allows the format of counter labels in logs and dump
|
/// 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
|
/// files (including the `CoverageGraph` graphviz file) to be changed at runtime, via environment
|
||||||
/// variable.
|
/// variable.
|
||||||
|
@ -276,7 +276,7 @@ impl DebugCounters {
|
||||||
self.some_counters.is_some()
|
self.some_counters.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_counter(&mut self, counter_kind: &CoverageKind, some_block_label: Option<String>) {
|
pub fn add_counter(&mut self, counter_kind: &BcbCounter, some_block_label: Option<String>) {
|
||||||
if let Some(counters) = &mut self.some_counters {
|
if let Some(counters) = &mut self.some_counters {
|
||||||
let id = counter_kind.as_operand();
|
let id = counter_kind.as_operand();
|
||||||
counters
|
counters
|
||||||
|
@ -291,21 +291,20 @@ impl DebugCounters {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format_counter(&self, counter_kind: &CoverageKind) -> String {
|
pub fn format_counter(&self, counter_kind: &BcbCounter) -> String {
|
||||||
match *counter_kind {
|
match *counter_kind {
|
||||||
CoverageKind::Counter { .. } => {
|
BcbCounter::Counter { .. } => {
|
||||||
format!("Counter({})", self.format_counter_kind(counter_kind))
|
format!("Counter({})", self.format_counter_kind(counter_kind))
|
||||||
}
|
}
|
||||||
CoverageKind::Expression { .. } => {
|
BcbCounter::Expression { .. } => {
|
||||||
format!("Expression({})", self.format_counter_kind(counter_kind))
|
format!("Expression({})", self.format_counter_kind(counter_kind))
|
||||||
}
|
}
|
||||||
CoverageKind::Unreachable { .. } => "Unreachable".to_owned(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_counter_kind(&self, counter_kind: &CoverageKind) -> String {
|
fn format_counter_kind(&self, counter_kind: &BcbCounter) -> String {
|
||||||
let counter_format = &debug_options().counter_format;
|
let counter_format = &debug_options().counter_format;
|
||||||
if let CoverageKind::Expression { id, lhs, op, rhs } = *counter_kind {
|
if let BcbCounter::Expression { id, lhs, op, rhs } = *counter_kind {
|
||||||
if counter_format.operation {
|
if counter_format.operation {
|
||||||
return format!(
|
return format!(
|
||||||
"{}{} {} {}",
|
"{}{} {} {}",
|
||||||
|
@ -346,7 +345,7 @@ impl DebugCounters {
|
||||||
}
|
}
|
||||||
if let Some(counters) = &self.some_counters {
|
if let Some(counters) = &self.some_counters {
|
||||||
if let Some(DebugCounter { counter_kind, some_block_label }) = counters.get(&operand) {
|
if let Some(DebugCounter { counter_kind, some_block_label }) = counters.get(&operand) {
|
||||||
if let CoverageKind::Expression { .. } = counter_kind {
|
if let BcbCounter::Expression { .. } = counter_kind {
|
||||||
if let Some(label) = some_block_label && debug_options().counter_format.block {
|
if let Some(label) = some_block_label && debug_options().counter_format.block {
|
||||||
return format!(
|
return format!(
|
||||||
"{}:({})",
|
"{}:({})",
|
||||||
|
@ -366,12 +365,12 @@ impl DebugCounters {
|
||||||
/// A non-public support class to `DebugCounters`.
|
/// A non-public support class to `DebugCounters`.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct DebugCounter {
|
struct DebugCounter {
|
||||||
counter_kind: CoverageKind,
|
counter_kind: BcbCounter,
|
||||||
some_block_label: Option<String>,
|
some_block_label: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DebugCounter {
|
impl DebugCounter {
|
||||||
fn new(counter_kind: CoverageKind, some_block_label: Option<String>) -> Self {
|
fn new(counter_kind: BcbCounter, some_block_label: Option<String>) -> Self {
|
||||||
Self { counter_kind, some_block_label }
|
Self { counter_kind, some_block_label }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -380,9 +379,9 @@ impl DebugCounter {
|
||||||
/// a Graphviz (.dot file) representation of the `CoverageGraph`, for debugging purposes.
|
/// a Graphviz (.dot file) representation of the `CoverageGraph`, for debugging purposes.
|
||||||
pub(super) struct GraphvizData {
|
pub(super) struct GraphvizData {
|
||||||
some_bcb_to_coverage_spans_with_counters:
|
some_bcb_to_coverage_spans_with_counters:
|
||||||
Option<FxHashMap<BasicCoverageBlock, Vec<(CoverageSpan, CoverageKind)>>>,
|
Option<FxHashMap<BasicCoverageBlock, Vec<(CoverageSpan, BcbCounter)>>>,
|
||||||
some_bcb_to_dependency_counters: Option<FxHashMap<BasicCoverageBlock, Vec<CoverageKind>>>,
|
some_bcb_to_dependency_counters: Option<FxHashMap<BasicCoverageBlock, Vec<BcbCounter>>>,
|
||||||
some_edge_to_counter: Option<FxHashMap<(BasicCoverageBlock, BasicBlock), CoverageKind>>,
|
some_edge_to_counter: Option<FxHashMap<(BasicCoverageBlock, BasicBlock), BcbCounter>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GraphvizData {
|
impl GraphvizData {
|
||||||
|
@ -409,7 +408,7 @@ impl GraphvizData {
|
||||||
&mut self,
|
&mut self,
|
||||||
bcb: BasicCoverageBlock,
|
bcb: BasicCoverageBlock,
|
||||||
coverage_span: &CoverageSpan,
|
coverage_span: &CoverageSpan,
|
||||||
counter_kind: &CoverageKind,
|
counter_kind: &BcbCounter,
|
||||||
) {
|
) {
|
||||||
if let Some(bcb_to_coverage_spans_with_counters) =
|
if let Some(bcb_to_coverage_spans_with_counters) =
|
||||||
self.some_bcb_to_coverage_spans_with_counters.as_mut()
|
self.some_bcb_to_coverage_spans_with_counters.as_mut()
|
||||||
|
@ -424,7 +423,7 @@ impl GraphvizData {
|
||||||
pub fn get_bcb_coverage_spans_with_counters(
|
pub fn get_bcb_coverage_spans_with_counters(
|
||||||
&self,
|
&self,
|
||||||
bcb: BasicCoverageBlock,
|
bcb: BasicCoverageBlock,
|
||||||
) -> Option<&[(CoverageSpan, CoverageKind)]> {
|
) -> Option<&[(CoverageSpan, BcbCounter)]> {
|
||||||
if let Some(bcb_to_coverage_spans_with_counters) =
|
if let Some(bcb_to_coverage_spans_with_counters) =
|
||||||
self.some_bcb_to_coverage_spans_with_counters.as_ref()
|
self.some_bcb_to_coverage_spans_with_counters.as_ref()
|
||||||
{
|
{
|
||||||
|
@ -437,7 +436,7 @@ impl GraphvizData {
|
||||||
pub fn add_bcb_dependency_counter(
|
pub fn add_bcb_dependency_counter(
|
||||||
&mut self,
|
&mut self,
|
||||||
bcb: BasicCoverageBlock,
|
bcb: BasicCoverageBlock,
|
||||||
counter_kind: &CoverageKind,
|
counter_kind: &BcbCounter,
|
||||||
) {
|
) {
|
||||||
if let Some(bcb_to_dependency_counters) = self.some_bcb_to_dependency_counters.as_mut() {
|
if let Some(bcb_to_dependency_counters) = self.some_bcb_to_dependency_counters.as_mut() {
|
||||||
bcb_to_dependency_counters
|
bcb_to_dependency_counters
|
||||||
|
@ -447,7 +446,7 @@ impl GraphvizData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_bcb_dependency_counters(&self, bcb: BasicCoverageBlock) -> Option<&[CoverageKind]> {
|
pub fn get_bcb_dependency_counters(&self, bcb: BasicCoverageBlock) -> Option<&[BcbCounter]> {
|
||||||
if let Some(bcb_to_dependency_counters) = self.some_bcb_to_dependency_counters.as_ref() {
|
if let Some(bcb_to_dependency_counters) = self.some_bcb_to_dependency_counters.as_ref() {
|
||||||
bcb_to_dependency_counters.get(&bcb).map(Deref::deref)
|
bcb_to_dependency_counters.get(&bcb).map(Deref::deref)
|
||||||
} else {
|
} else {
|
||||||
|
@ -459,7 +458,7 @@ impl GraphvizData {
|
||||||
&mut self,
|
&mut self,
|
||||||
from_bcb: BasicCoverageBlock,
|
from_bcb: BasicCoverageBlock,
|
||||||
to_bb: BasicBlock,
|
to_bb: BasicBlock,
|
||||||
counter_kind: &CoverageKind,
|
counter_kind: &BcbCounter,
|
||||||
) {
|
) {
|
||||||
if let Some(edge_to_counter) = self.some_edge_to_counter.as_mut() {
|
if let Some(edge_to_counter) = self.some_edge_to_counter.as_mut() {
|
||||||
edge_to_counter
|
edge_to_counter
|
||||||
|
@ -472,7 +471,7 @@ impl GraphvizData {
|
||||||
&self,
|
&self,
|
||||||
from_bcb: BasicCoverageBlock,
|
from_bcb: BasicCoverageBlock,
|
||||||
to_bb: BasicBlock,
|
to_bb: BasicBlock,
|
||||||
) -> Option<&CoverageKind> {
|
) -> Option<&BcbCounter> {
|
||||||
if let Some(edge_to_counter) = self.some_edge_to_counter.as_ref() {
|
if let Some(edge_to_counter) = self.some_edge_to_counter.as_ref() {
|
||||||
edge_to_counter.get(&(from_bcb, to_bb))
|
edge_to_counter.get(&(from_bcb, to_bb))
|
||||||
} else {
|
} else {
|
||||||
|
@ -488,7 +487,7 @@ impl GraphvizData {
|
||||||
pub(super) struct UsedExpressions {
|
pub(super) struct UsedExpressions {
|
||||||
some_used_expression_operands: Option<FxHashMap<Operand, Vec<ExpressionId>>>,
|
some_used_expression_operands: Option<FxHashMap<Operand, Vec<ExpressionId>>>,
|
||||||
some_unused_expressions:
|
some_unused_expressions:
|
||||||
Option<Vec<(CoverageKind, Option<BasicCoverageBlock>, BasicCoverageBlock)>>,
|
Option<Vec<(BcbCounter, Option<BasicCoverageBlock>, BasicCoverageBlock)>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UsedExpressions {
|
impl UsedExpressions {
|
||||||
|
@ -506,16 +505,16 @@ impl UsedExpressions {
|
||||||
self.some_used_expression_operands.is_some()
|
self.some_used_expression_operands.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_expression_operands(&mut self, expression: &CoverageKind) {
|
pub fn add_expression_operands(&mut self, expression: &BcbCounter) {
|
||||||
if let Some(used_expression_operands) = self.some_used_expression_operands.as_mut() {
|
if let Some(used_expression_operands) = self.some_used_expression_operands.as_mut() {
|
||||||
if let CoverageKind::Expression { id, lhs, rhs, .. } = *expression {
|
if let BcbCounter::Expression { id, lhs, rhs, .. } = *expression {
|
||||||
used_expression_operands.entry(lhs).or_insert_with(Vec::new).push(id);
|
used_expression_operands.entry(lhs).or_insert_with(Vec::new).push(id);
|
||||||
used_expression_operands.entry(rhs).or_insert_with(Vec::new).push(id);
|
used_expression_operands.entry(rhs).or_insert_with(Vec::new).push(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expression_is_used(&self, expression: &CoverageKind) -> bool {
|
pub fn expression_is_used(&self, expression: &BcbCounter) -> bool {
|
||||||
if let Some(used_expression_operands) = self.some_used_expression_operands.as_ref() {
|
if let Some(used_expression_operands) = self.some_used_expression_operands.as_ref() {
|
||||||
used_expression_operands.contains_key(&expression.as_operand())
|
used_expression_operands.contains_key(&expression.as_operand())
|
||||||
} else {
|
} else {
|
||||||
|
@ -525,7 +524,7 @@ impl UsedExpressions {
|
||||||
|
|
||||||
pub fn add_unused_expression_if_not_found(
|
pub fn add_unused_expression_if_not_found(
|
||||||
&mut self,
|
&mut self,
|
||||||
expression: &CoverageKind,
|
expression: &BcbCounter,
|
||||||
edge_from_bcb: Option<BasicCoverageBlock>,
|
edge_from_bcb: Option<BasicCoverageBlock>,
|
||||||
target_bcb: BasicCoverageBlock,
|
target_bcb: BasicCoverageBlock,
|
||||||
) {
|
) {
|
||||||
|
@ -540,11 +539,11 @@ impl UsedExpressions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the list of unused counters (if any) as a tuple with the counter (`CoverageKind`),
|
/// Return the list of unused counters (if any) as a tuple with the counter (`BcbCounter`),
|
||||||
/// optional `from_bcb` (if it was an edge counter), and `target_bcb`.
|
/// optional `from_bcb` (if it was an edge counter), and `target_bcb`.
|
||||||
pub fn get_unused_expressions(
|
pub fn get_unused_expressions(
|
||||||
&self,
|
&self,
|
||||||
) -> Vec<(CoverageKind, Option<BasicCoverageBlock>, BasicCoverageBlock)> {
|
) -> Vec<(BcbCounter, Option<BasicCoverageBlock>, BasicCoverageBlock)> {
|
||||||
if let Some(unused_expressions) = self.some_unused_expressions.as_ref() {
|
if let Some(unused_expressions) = self.some_unused_expressions.as_ref() {
|
||||||
unused_expressions.clone()
|
unused_expressions.clone()
|
||||||
} else {
|
} else {
|
||||||
|
@ -560,7 +559,7 @@ impl UsedExpressions {
|
||||||
bcb_counters_without_direct_coverage_spans: &[(
|
bcb_counters_without_direct_coverage_spans: &[(
|
||||||
Option<BasicCoverageBlock>,
|
Option<BasicCoverageBlock>,
|
||||||
BasicCoverageBlock,
|
BasicCoverageBlock,
|
||||||
CoverageKind,
|
BcbCounter,
|
||||||
)],
|
)],
|
||||||
) {
|
) {
|
||||||
if self.is_enabled() {
|
if self.is_enabled() {
|
||||||
|
@ -662,7 +661,7 @@ pub(super) fn dump_coverage_graphviz<'tcx>(
|
||||||
basic_coverage_blocks: &CoverageGraph,
|
basic_coverage_blocks: &CoverageGraph,
|
||||||
coverage_counters: &CoverageCounters,
|
coverage_counters: &CoverageCounters,
|
||||||
graphviz_data: &GraphvizData,
|
graphviz_data: &GraphvizData,
|
||||||
intermediate_expressions: &[CoverageKind],
|
intermediate_expressions: &[BcbCounter],
|
||||||
debug_used_expressions: &UsedExpressions,
|
debug_used_expressions: &UsedExpressions,
|
||||||
) {
|
) {
|
||||||
let debug_counters = &coverage_counters.debug_counters;
|
let debug_counters = &coverage_counters.debug_counters;
|
||||||
|
@ -743,9 +742,9 @@ fn bcb_to_string_sections<'tcx>(
|
||||||
coverage_counters: &CoverageCounters,
|
coverage_counters: &CoverageCounters,
|
||||||
bcb: BasicCoverageBlock,
|
bcb: BasicCoverageBlock,
|
||||||
bcb_data: &BasicCoverageBlockData,
|
bcb_data: &BasicCoverageBlockData,
|
||||||
some_coverage_spans_with_counters: Option<&[(CoverageSpan, CoverageKind)]>,
|
some_coverage_spans_with_counters: Option<&[(CoverageSpan, BcbCounter)]>,
|
||||||
some_dependency_counters: Option<&[CoverageKind]>,
|
some_dependency_counters: Option<&[BcbCounter]>,
|
||||||
some_intermediate_expressions: Option<&[CoverageKind]>,
|
some_intermediate_expressions: Option<&[BcbCounter]>,
|
||||||
) -> Vec<String> {
|
) -> Vec<String> {
|
||||||
let debug_counters = &coverage_counters.debug_counters;
|
let debug_counters = &coverage_counters.debug_counters;
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,9 @@ mod spans;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use counters::CoverageCounters;
|
use self::counters::{BcbCounter, CoverageCounters};
|
||||||
use graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph};
|
use self::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph};
|
||||||
use spans::{CoverageSpan, CoverageSpans};
|
use self::spans::{CoverageSpan, CoverageSpans};
|
||||||
|
|
||||||
use crate::MirPass;
|
use crate::MirPass;
|
||||||
|
|
||||||
|
@ -270,8 +270,11 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
|
||||||
|
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
// Finally, inject the intermediate expressions collected along the way.
|
// Finally, inject the intermediate expressions collected along the way.
|
||||||
for intermediate_expression in self.coverage_counters.intermediate_expressions.drain(..) {
|
for intermediate_expression in &self.coverage_counters.intermediate_expressions {
|
||||||
inject_intermediate_expression(self.mir_body, intermediate_expression);
|
inject_intermediate_expression(
|
||||||
|
self.mir_body,
|
||||||
|
self.make_mir_coverage_kind(intermediate_expression),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,7 +317,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
|
||||||
|
|
||||||
inject_statement(
|
inject_statement(
|
||||||
self.mir_body,
|
self.mir_body,
|
||||||
counter_kind,
|
self.make_mir_coverage_kind(&counter_kind),
|
||||||
self.bcb_leader_bb(bcb),
|
self.bcb_leader_bb(bcb),
|
||||||
Some(code_region),
|
Some(code_region),
|
||||||
);
|
);
|
||||||
|
@ -362,7 +365,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
|
|
||||||
match counter_kind {
|
match counter_kind {
|
||||||
CoverageKind::Counter { .. } => {
|
BcbCounter::Counter { .. } => {
|
||||||
let inject_to_bb = if let Some(from_bcb) = edge_from_bcb {
|
let inject_to_bb = if let Some(from_bcb) = edge_from_bcb {
|
||||||
// The MIR edge starts `from_bb` (the outgoing / last BasicBlock in
|
// The MIR edge starts `from_bb` (the outgoing / last BasicBlock in
|
||||||
// `from_bcb`) and ends at `to_bb` (the incoming / first BasicBlock in the
|
// `from_bcb`) and ends at `to_bb` (the incoming / first BasicBlock in the
|
||||||
|
@ -395,12 +398,17 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
|
||||||
target_bb
|
target_bb
|
||||||
};
|
};
|
||||||
|
|
||||||
inject_statement(self.mir_body, counter_kind, inject_to_bb, None);
|
inject_statement(
|
||||||
|
self.mir_body,
|
||||||
|
self.make_mir_coverage_kind(&counter_kind),
|
||||||
|
inject_to_bb,
|
||||||
|
None,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
CoverageKind::Expression { .. } => {
|
BcbCounter::Expression { .. } => inject_intermediate_expression(
|
||||||
inject_intermediate_expression(self.mir_body, counter_kind)
|
self.mir_body,
|
||||||
}
|
self.make_mir_coverage_kind(&counter_kind),
|
||||||
_ => bug!("CoverageKind should be a counter"),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -421,9 +429,20 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn format_counter(&self, counter_kind: &CoverageKind) -> String {
|
fn format_counter(&self, counter_kind: &BcbCounter) -> String {
|
||||||
self.coverage_counters.debug_counters.format_counter(counter_kind)
|
self.coverage_counters.debug_counters.format_counter(counter_kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_mir_coverage_kind(&self, counter_kind: &BcbCounter) -> CoverageKind {
|
||||||
|
match *counter_kind {
|
||||||
|
BcbCounter::Counter { function_source_hash, id } => {
|
||||||
|
CoverageKind::Counter { function_source_hash, id }
|
||||||
|
}
|
||||||
|
BcbCounter::Expression { id, lhs, op, rhs } => {
|
||||||
|
CoverageKind::Expression { id, lhs, op, rhs }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inject_edge_counter_basic_block(
|
fn inject_edge_counter_basic_block(
|
||||||
|
|
|
@ -34,7 +34,6 @@ use itertools::Itertools;
|
||||||
use rustc_data_structures::graph::WithNumNodes;
|
use rustc_data_structures::graph::WithNumNodes;
|
||||||
use rustc_data_structures::graph::WithSuccessors;
|
use rustc_data_structures::graph::WithSuccessors;
|
||||||
use rustc_index::{Idx, IndexVec};
|
use rustc_index::{Idx, IndexVec};
|
||||||
use rustc_middle::mir::coverage::CoverageKind;
|
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_span::{self, BytePos, Pos, Span, DUMMY_SP};
|
use rustc_span::{self, BytePos, Pos, Span, DUMMY_SP};
|
||||||
|
@ -685,7 +684,7 @@ fn test_make_bcb_counters() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
0, // bcb1 has a `Counter` with id = 0
|
0, // bcb1 has a `Counter` with id = 0
|
||||||
match coverage_counters.bcb_counter(bcb1).expect("should have a counter") {
|
match coverage_counters.bcb_counter(bcb1).expect("should have a counter") {
|
||||||
CoverageKind::Counter { id, .. } => id,
|
counters::BcbCounter::Counter { id, .. } => id,
|
||||||
_ => panic!("expected a Counter"),
|
_ => panic!("expected a Counter"),
|
||||||
}
|
}
|
||||||
.as_u32()
|
.as_u32()
|
||||||
|
@ -695,7 +694,7 @@ fn test_make_bcb_counters() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
1, // bcb2 has a `Counter` with id = 1
|
1, // bcb2 has a `Counter` with id = 1
|
||||||
match coverage_counters.bcb_counter(bcb2).expect("should have a counter") {
|
match coverage_counters.bcb_counter(bcb2).expect("should have a counter") {
|
||||||
CoverageKind::Counter { id, .. } => id,
|
counters::BcbCounter::Counter { id, .. } => id,
|
||||||
_ => panic!("expected a Counter"),
|
_ => panic!("expected a Counter"),
|
||||||
}
|
}
|
||||||
.as_u32()
|
.as_u32()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue