@@ -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