@@ -3,24 +3,22 @@ pub use super::ffi::*;
3
3
use rustc_index::{IndexSlice, IndexVec};
4
4
use rustc_middle::bug;
5
5
use rustc_middle::mir::coverage::{
6
- CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId,
7
- InjectedExpressionIndex, MappedExpressionIndex, Op,
6
+ CodeRegion, CounterId, ExpressionId, MappedExpressionIndex, Op, Operand,
8
7
};
9
8
use rustc_middle::ty::Instance;
10
9
use rustc_middle::ty::TyCtxt;
11
10
12
11
#[derive(Clone, Debug, PartialEq)]
13
12
pub struct Expression {
14
- lhs: ExpressionOperandId ,
13
+ lhs: Operand ,
15
14
op: Op,
16
- rhs: ExpressionOperandId ,
15
+ rhs: Operand ,
17
16
region: Option<CodeRegion>,
18
17
}
19
18
20
19
/// Collects all of the coverage regions associated with (a) injected counters, (b) counter
21
20
/// expressions (additions or subtraction), and (c) unreachable regions (always counted as zero),
22
- /// for a given Function. Counters and counter expressions have non-overlapping `id`s because they
23
- /// can both be operands in an expression. This struct also stores the `function_source_hash`,
21
+ /// for a given Function. This struct also stores the `function_source_hash`,
24
22
/// computed during instrumentation, and forwarded with counters.
25
23
///
26
24
/// Note, it may be important to understand LLVM's definitions of `unreachable` regions versus "gap
@@ -34,8 +32,8 @@ pub struct FunctionCoverage<'tcx> {
34
32
instance: Instance<'tcx>,
35
33
source_hash: u64,
36
34
is_used: bool,
37
- counters: IndexVec<CounterValueReference , Option<CodeRegion>>,
38
- expressions: IndexVec<InjectedExpressionIndex , Option<Expression>>,
35
+ counters: IndexVec<CounterId , Option<CodeRegion>>,
36
+ expressions: IndexVec<ExpressionId , Option<Expression>>,
39
37
unreachable_regions: Vec<CodeRegion>,
40
38
}
41
39
@@ -82,48 +80,36 @@ impl<'tcx> FunctionCoverage<'tcx> {
82
80
}
83
81
84
82
/// Adds a code region to be counted by an injected counter intrinsic.
85
- pub fn add_counter(&mut self, id: CounterValueReference , region: CodeRegion) {
83
+ pub fn add_counter(&mut self, id: CounterId , region: CodeRegion) {
86
84
if let Some(previous_region) = self.counters[id].replace(region.clone()) {
87
85
assert_eq!(previous_region, region, "add_counter: code region for id changed");
88
86
}
89
87
}
90
88
91
89
/// Both counters and "counter expressions" (or simply, "expressions") can be operands in other
92
- /// expressions. Expression IDs start from `u32::MAX` and go down, so the range of expression
93
- /// IDs will not overlap with the range of counter IDs. Counters and expressions can be added in
94
- /// any order, and expressions can still be assigned contiguous (though descending) IDs, without
95
- /// knowing what the last counter ID will be.
96
- ///
97
- /// When storing the expression data in the `expressions` vector in the `FunctionCoverage`
98
- /// struct, its vector index is computed, from the given expression ID, by subtracting from
99
- /// `u32::MAX`.
100
- ///
101
- /// Since the expression operands (`lhs` and `rhs`) can reference either counters or
102
- /// expressions, an operand that references an expression also uses its original ID, descending
103
- /// from `u32::MAX`. Theses operands are translated only during code generation, after all
104
- /// counters and expressions have been added.
90
+ /// expressions. These are tracked as separate variants of `Operand`, so there is no ambiguity
91
+ /// between operands that are counter IDs and operands that are expression IDs.
105
92
pub fn add_counter_expression(
106
93
&mut self,
107
- expression_id: InjectedExpressionId ,
108
- lhs: ExpressionOperandId ,
94
+ expression_id: ExpressionId ,
95
+ lhs: Operand ,
109
96
op: Op,
110
- rhs: ExpressionOperandId ,
97
+ rhs: Operand ,
111
98
region: Option<CodeRegion>,
112
99
) {
113
100
debug!(
114
101
"add_counter_expression({:?}, lhs={:?}, op={:?}, rhs={:?} at {:?}",
115
102
expression_id, lhs, op, rhs, region
116
103
);
117
- let expression_index = self.expression_index(u32::from(expression_id));
118
104
debug_assert!(
119
- expression_index .as_usize() < self.expressions.len(),
120
- "expression_index {} is out of range for expressions.len() = {}
105
+ expression_id .as_usize() < self.expressions.len(),
106
+ "expression_id {} is out of range for expressions.len() = {}
121
107
for {:?}",
122
- expression_index .as_usize(),
108
+ expression_id .as_usize(),
123
109
self.expressions.len(),
124
110
self,
125
111
);
126
- if let Some(previous_expression) = self.expressions[expression_index ].replace(Expression {
112
+ if let Some(previous_expression) = self.expressions[expression_id ].replace(Expression {
127
113
lhs,
128
114
op,
129
115
rhs,
@@ -186,14 +172,11 @@ impl<'tcx> FunctionCoverage<'tcx> {
186
172
187
173
// This closure converts any `Expression` operand (`lhs` or `rhs` of the `Op::Add` or
188
174
// `Op::Subtract` operation) into its native `llvm::coverage::Counter::CounterKind` type
189
- // and value. Operand ID value `0` maps to `CounterKind::Zero`; values in the known range
190
- // of injected LLVM counters map to `CounterKind::CounterValueReference` (and the value
191
- // matches the injected counter index); and any other value is converted into a
192
- // `CounterKind::Expression` with the expression's `new_index`.
175
+ // and value.
193
176
//
194
177
// Expressions will be returned from this function in a sequential vector (array) of
195
178
// `CounterExpression`, so the expression IDs must be mapped from their original,
196
- // potentially sparse set of indexes, originally in reverse order from `u32::MAX` .
179
+ // potentially sparse set of indexes.
197
180
//
198
181
// An `Expression` as an operand will have already been encountered as an `Expression` with
199
182
// operands, so its new_index will already have been generated (as a 1-up index value).
@@ -206,34 +189,19 @@ impl<'tcx> FunctionCoverage<'tcx> {
206
189
// `expression_index`s lower than the referencing `Expression`. Therefore, it is
207
190
// reasonable to look up the new index of an expression operand while the `new_indexes`
208
191
// vector is only complete up to the current `ExpressionIndex`.
209
- let id_to_counter = |new_indexes: &IndexSlice<
210
- InjectedExpressionIndex,
211
- Option<MappedExpressionIndex>,
212
- >,
213
- id: ExpressionOperandId| {
214
- if id == ExpressionOperandId::ZERO {
215
- Some(Counter::zero())
216
- } else if id.index() < self.counters.len() {
217
- debug_assert!(
218
- id.index() > 0,
219
- "ExpressionOperandId indexes for counters are 1-based, but this id={}",
220
- id.index()
221
- );
222
- // Note: Some codegen-injected Counters may be only referenced by `Expression`s,
223
- // and may not have their own `CodeRegion`s,
224
- let index = CounterValueReference::from(id.index());
225
- // Note, the conversion to LLVM `Counter` adjusts the index to be zero-based.
226
- Some(Counter::counter_value_reference(index))
227
- } else {
228
- let index = self.expression_index(u32::from(id));
192
+ type NewIndexes = IndexSlice<ExpressionId, Option<MappedExpressionIndex>>;
193
+ let id_to_counter = |new_indexes: &NewIndexes, operand: Operand| match operand {
194
+ Operand::Zero => Some(Counter::zero()),
195
+ Operand::Counter(id) => Some(Counter::counter_value_reference(id)),
196
+ Operand::Expression(id) => {
229
197
self.expressions
230
- .get(index )
198
+ .get(id )
231
199
.expect("expression id is out of range")
232
200
.as_ref()
233
201
// If an expression was optimized out, assume it would have produced a count
234
202
// of zero. This ensures that expressions dependent on optimized-out
235
203
// expressions are still valid.
236
- .map_or(Some(Counter::zero()), |_| new_indexes[index ].map(Counter::expression))
204
+ .map_or(Some(Counter::zero()), |_| new_indexes[id ].map(Counter::expression))
237
205
}
238
206
};
239
207
@@ -340,9 +308,4 @@ impl<'tcx> FunctionCoverage<'tcx> {
340
308
fn unreachable_regions(&self) -> impl Iterator<Item = (Counter, &CodeRegion)> {
341
309
self.unreachable_regions.iter().map(|region| (Counter::zero(), region))
342
310
}
343
-
344
- fn expression_index(&self, id_descending_from_max: u32) -> InjectedExpressionIndex {
345
- debug_assert!(id_descending_from_max >= self.counters.len() as u32);
346
- InjectedExpressionIndex::from(u32::MAX - id_descending_from_max)
347
- }
348
311
}
0 commit comments