Skip to content

Commit 0510a15

Browse files
committed
Auto merge of #114791 - Zalathar:bcb-counter, r=cjgillot
coverage: Give the instrumentor its own counter type, separate from MIR Within the MIR representation of coverage data, `CoverageKind` is an important part of `StatementKind::Coverage`, but the `InstrumentCoverage` pass also uses it heavily as an internal data structure. This means that any change to `CoverageKind` also needs to update all of the internal parts of `InstrumentCoverage` that manipulate it directly, making the MIR representation difficult to modify. --- This change fixes that by giving the instrumentor its own `BcbCounter` type for internal use, which is then converted to a `CoverageKind` when injecting coverage information into MIR. The main change is mostly mechanical, because the initial `BcbCounter` is drop-in compatible with `CoverageKind`, minus the unnecessary `CoverageKind::Unreachable` variant. I've then removed the `function_source_hash` field from `BcbCounter::Counter`, as a small example of how the two types can now usefully differ from each other. Every counter in a MIR-level function should have the same source hash, so we can supply the hash during the conversion to `CoverageKind::Counter` instead. --- *Background:* BCB stands for “basic coverage block”, which is a node in the simplified control-flow graph used by coverage instrumentation. The instrumentor pass uses the function's actual MIR control-flow graph to build a simplified BCB graph, then assigns coverage counters and counter expressions to various nodes/edges in that simplified graph, and then finally injects corresponding coverage information into the underlying MIR.
2 parents c0b6ffa + 72f4c78 commit 0510a15

File tree

5 files changed

+146
-102
lines changed

5 files changed

+146
-102
lines changed

compiler/rustc_middle/src/mir/coverage.rs

-15
Original file line numberDiff line numberDiff line change
@@ -96,21 +96,6 @@ pub enum CoverageKind {
9696
Unreachable,
9797
}
9898

99-
impl CoverageKind {
100-
pub fn as_operand(&self) -> Operand {
101-
use CoverageKind::*;
102-
match *self {
103-
Counter { id, .. } => Operand::Counter(id),
104-
Expression { id, .. } => Operand::Expression(id),
105-
Unreachable => bug!("Unreachable coverage cannot be part of an expression"),
106-
}
107-
}
108-
109-
pub fn is_expression(&self) -> bool {
110-
matches!(self, Self::Expression { .. })
111-
}
112-
}
113-
11499
impl Debug for CoverageKind {
115100
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
116101
use CoverageKind::*;

compiler/rustc_mir_transform/src/coverage/counters.rs

+62-25
Original file line numberDiff line numberDiff line change
@@ -14,36 +14,76 @@ use rustc_index::bit_set::BitSet;
1414
use rustc_index::IndexVec;
1515
use rustc_middle::mir::coverage::*;
1616

17+
use std::fmt::{self, Debug};
18+
19+
/// The coverage counter or counter expression associated with a particular
20+
/// BCB node or BCB edge.
21+
#[derive(Clone)]
22+
pub(super) enum BcbCounter {
23+
Counter { id: CounterId },
24+
Expression { id: ExpressionId, lhs: Operand, op: Op, rhs: Operand },
25+
}
26+
27+
impl BcbCounter {
28+
fn is_expression(&self) -> bool {
29+
matches!(self, Self::Expression { .. })
30+
}
31+
32+
pub(super) fn as_operand(&self) -> Operand {
33+
match *self {
34+
BcbCounter::Counter { id, .. } => Operand::Counter(id),
35+
BcbCounter::Expression { id, .. } => Operand::Expression(id),
36+
}
37+
}
38+
}
39+
40+
impl Debug for BcbCounter {
41+
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
42+
match self {
43+
Self::Counter { id, .. } => write!(fmt, "Counter({:?})", id.index()),
44+
Self::Expression { id, lhs, op, rhs } => write!(
45+
fmt,
46+
"Expression({:?}) = {:?} {} {:?}",
47+
id.index(),
48+
lhs,
49+
match op {
50+
Op::Add => "+",
51+
Op::Subtract => "-",
52+
},
53+
rhs,
54+
),
55+
}
56+
}
57+
}
58+
1759
/// Generates and stores coverage counter and coverage expression information
1860
/// associated with nodes/edges in the BCB graph.
1961
pub(super) struct CoverageCounters {
20-
function_source_hash: u64,
2162
next_counter_id: CounterId,
2263
next_expression_id: ExpressionId,
2364

2465
/// Coverage counters/expressions that are associated with individual BCBs.
25-
bcb_counters: IndexVec<BasicCoverageBlock, Option<CoverageKind>>,
66+
bcb_counters: IndexVec<BasicCoverageBlock, Option<BcbCounter>>,
2667
/// Coverage counters/expressions that are associated with the control-flow
2768
/// edge between two BCBs.
28-
bcb_edge_counters: FxHashMap<(BasicCoverageBlock, BasicCoverageBlock), CoverageKind>,
69+
bcb_edge_counters: FxHashMap<(BasicCoverageBlock, BasicCoverageBlock), BcbCounter>,
2970
/// Tracks which BCBs have a counter associated with some incoming edge.
3071
/// Only used by debug assertions, to verify that BCBs with incoming edge
3172
/// counters do not have their own physical counters (expressions are allowed).
3273
bcb_has_incoming_edge_counters: BitSet<BasicCoverageBlock>,
3374
/// Expression nodes that are not directly associated with any particular
3475
/// BCB/edge, but are needed as operands to more complex expressions.
35-
/// These are always `CoverageKind::Expression`.
36-
pub(super) intermediate_expressions: Vec<CoverageKind>,
76+
/// These are always [`BcbCounter::Expression`].
77+
pub(super) intermediate_expressions: Vec<BcbCounter>,
3778

3879
pub debug_counters: DebugCounters,
3980
}
4081

4182
impl CoverageCounters {
42-
pub(super) fn new(function_source_hash: u64, basic_coverage_blocks: &CoverageGraph) -> Self {
83+
pub(super) fn new(basic_coverage_blocks: &CoverageGraph) -> Self {
4384
let num_bcbs = basic_coverage_blocks.num_nodes();
4485

4586
Self {
46-
function_source_hash,
4787
next_counter_id: CounterId::START,
4888
next_expression_id: ExpressionId::START,
4989

@@ -57,12 +97,12 @@ impl CoverageCounters {
5797
}
5898

5999
/// Activate the `DebugCounters` data structures, to provide additional debug formatting
60-
/// features when formatting `CoverageKind` (counter) values.
100+
/// features when formatting [`BcbCounter`] (counter) values.
61101
pub fn enable_debug(&mut self) {
62102
self.debug_counters.enable();
63103
}
64104

65-
/// Makes `CoverageKind` `Counter`s and `Expressions` for the `BasicCoverageBlock`s directly or
105+
/// Makes [`BcbCounter`] `Counter`s and `Expressions` for the `BasicCoverageBlock`s directly or
66106
/// indirectly associated with `CoverageSpans`, and accumulates additional `Expression`s
67107
/// representing intermediate values.
68108
pub fn make_bcb_counters(
@@ -73,14 +113,11 @@ impl CoverageCounters {
73113
MakeBcbCounters::new(self, basic_coverage_blocks).make_bcb_counters(coverage_spans)
74114
}
75115

76-
fn make_counter<F>(&mut self, debug_block_label_fn: F) -> CoverageKind
116+
fn make_counter<F>(&mut self, debug_block_label_fn: F) -> BcbCounter
77117
where
78118
F: Fn() -> Option<String>,
79119
{
80-
let counter = CoverageKind::Counter {
81-
function_source_hash: self.function_source_hash,
82-
id: self.next_counter(),
83-
};
120+
let counter = BcbCounter::Counter { id: self.next_counter() };
84121
if self.debug_counters.is_enabled() {
85122
self.debug_counters.add_counter(&counter, (debug_block_label_fn)());
86123
}
@@ -93,19 +130,19 @@ impl CoverageCounters {
93130
op: Op,
94131
rhs: Operand,
95132
debug_block_label_fn: F,
96-
) -> CoverageKind
133+
) -> BcbCounter
97134
where
98135
F: Fn() -> Option<String>,
99136
{
100137
let id = self.next_expression();
101-
let expression = CoverageKind::Expression { id, lhs, op, rhs };
138+
let expression = BcbCounter::Expression { id, lhs, op, rhs };
102139
if self.debug_counters.is_enabled() {
103140
self.debug_counters.add_counter(&expression, (debug_block_label_fn)());
104141
}
105142
expression
106143
}
107144

108-
pub fn make_identity_counter(&mut self, counter_operand: Operand) -> CoverageKind {
145+
pub fn make_identity_counter(&mut self, counter_operand: Operand) -> BcbCounter {
109146
let some_debug_block_label = if self.debug_counters.is_enabled() {
110147
self.debug_counters.some_block_label(counter_operand).cloned()
111148
} else {
@@ -134,7 +171,7 @@ impl CoverageCounters {
134171
fn set_bcb_counter(
135172
&mut self,
136173
bcb: BasicCoverageBlock,
137-
counter_kind: CoverageKind,
174+
counter_kind: BcbCounter,
138175
) -> Result<Operand, Error> {
139176
debug_assert!(
140177
// If the BCB has an edge counter (to be injected into a new `BasicBlock`), it can also
@@ -158,7 +195,7 @@ impl CoverageCounters {
158195
&mut self,
159196
from_bcb: BasicCoverageBlock,
160197
to_bcb: BasicCoverageBlock,
161-
counter_kind: CoverageKind,
198+
counter_kind: BcbCounter,
162199
) -> Result<Operand, Error> {
163200
if level_enabled!(tracing::Level::DEBUG) {
164201
// If the BCB has an edge counter (to be injected into a new `BasicBlock`), it can also
@@ -183,25 +220,25 @@ impl CoverageCounters {
183220
}
184221
}
185222

186-
pub(super) fn bcb_counter(&self, bcb: BasicCoverageBlock) -> Option<&CoverageKind> {
223+
pub(super) fn bcb_counter(&self, bcb: BasicCoverageBlock) -> Option<&BcbCounter> {
187224
self.bcb_counters[bcb].as_ref()
188225
}
189226

190-
pub(super) fn take_bcb_counter(&mut self, bcb: BasicCoverageBlock) -> Option<CoverageKind> {
227+
pub(super) fn take_bcb_counter(&mut self, bcb: BasicCoverageBlock) -> Option<BcbCounter> {
191228
self.bcb_counters[bcb].take()
192229
}
193230

194231
pub(super) fn drain_bcb_counters(
195232
&mut self,
196-
) -> impl Iterator<Item = (BasicCoverageBlock, CoverageKind)> + '_ {
233+
) -> impl Iterator<Item = (BasicCoverageBlock, BcbCounter)> + '_ {
197234
self.bcb_counters
198235
.iter_enumerated_mut()
199236
.filter_map(|(bcb, counter)| Some((bcb, counter.take()?)))
200237
}
201238

202239
pub(super) fn drain_bcb_edge_counters(
203240
&mut self,
204-
) -> impl Iterator<Item = ((BasicCoverageBlock, BasicCoverageBlock), CoverageKind)> + '_ {
241+
) -> impl Iterator<Item = ((BasicCoverageBlock, BasicCoverageBlock), BcbCounter)> + '_ {
205242
self.bcb_edge_counters.drain()
206243
}
207244
}
@@ -653,7 +690,7 @@ impl<'a> MakeBcbCounters<'a> {
653690
self.branch_counter(branch).is_none()
654691
}
655692

656-
fn branch_counter(&self, branch: &BcbBranch) -> Option<&CoverageKind> {
693+
fn branch_counter(&self, branch: &BcbBranch) -> Option<&BcbCounter> {
657694
let to_bcb = branch.target_bcb;
658695
if let Some(from_bcb) = branch.edge_from_bcb {
659696
self.coverage_counters.bcb_edge_counters.get(&(from_bcb, to_bcb))
@@ -675,7 +712,7 @@ impl<'a> MakeBcbCounters<'a> {
675712
}
676713

677714
#[inline]
678-
fn format_counter(&self, counter_kind: &CoverageKind) -> String {
715+
fn format_counter(&self, counter_kind: &BcbCounter) -> String {
679716
self.coverage_counters.debug_counters.format_counter(counter_kind)
680717
}
681718
}

0 commit comments

Comments
 (0)