1
+ use rustc_index:: vec:: IndexVec ;
1
2
use rustc_middle:: ty:: Instance ;
2
3
use rustc_middle:: ty:: TyCtxt ;
3
4
use rustc_span:: source_map:: { Pos , SourceMap } ;
@@ -7,6 +8,34 @@ use std::cmp::{Ord, Ordering};
7
8
use std:: fmt;
8
9
use std:: path:: PathBuf ;
9
10
11
+ rustc_index:: newtype_index! {
12
+ pub struct ExpressionOperandId {
13
+ DEBUG_FORMAT = "ExpressionOperandId({})" ,
14
+ MAX = 0xFFFF_FFFF ,
15
+ }
16
+ }
17
+
18
+ rustc_index:: newtype_index! {
19
+ pub struct CounterValueReference {
20
+ DEBUG_FORMAT = "CounterValueReference({})" ,
21
+ MAX = 0xFFFF_FFFF ,
22
+ }
23
+ }
24
+
25
+ rustc_index:: newtype_index! {
26
+ pub struct InjectedExpressionIndex {
27
+ DEBUG_FORMAT = "InjectedExpressionIndex({})" ,
28
+ MAX = 0xFFFF_FFFF ,
29
+ }
30
+ }
31
+
32
+ rustc_index:: newtype_index! {
33
+ pub struct MappedExpressionIndex {
34
+ DEBUG_FORMAT = "MappedExpressionIndex({})" ,
35
+ MAX = 0xFFFF_FFFF ,
36
+ }
37
+ }
38
+
10
39
/// Aligns with [llvm::coverage::Counter::CounterKind](https://github.com/rust-lang/llvm-project/blob/rustc/10.0-2020-05-05/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L91)
11
40
#[ derive( Copy , Clone , Debug ) ]
12
41
#[ repr( C ) ]
@@ -38,12 +67,12 @@ impl Counter {
38
67
Self { kind : CounterKind :: Zero , id : 0 }
39
68
}
40
69
41
- pub fn counter_value_reference ( counter_id : u32 ) -> Self {
42
- Self { kind : CounterKind :: CounterValueReference , id : counter_id }
70
+ pub fn counter_value_reference ( counter_id : CounterValueReference ) -> Self {
71
+ Self { kind : CounterKind :: CounterValueReference , id : counter_id. into ( ) }
43
72
}
44
73
45
- pub fn expression ( final_expression_index : u32 ) -> Self {
46
- Self { kind : CounterKind :: Expression , id : final_expression_index }
74
+ pub fn expression ( mapped_expression_index : MappedExpressionIndex ) -> Self {
75
+ Self { kind : CounterKind :: Expression , id : mapped_expression_index . into ( ) }
47
76
}
48
77
}
49
78
@@ -143,9 +172,9 @@ impl Region {
143
172
144
173
#[ derive( Clone , Debug ) ]
145
174
pub struct ExpressionRegion {
146
- lhs : u32 ,
175
+ lhs : ExpressionOperandId ,
147
176
op : ExprKind ,
148
- rhs : u32 ,
177
+ rhs : ExpressionOperandId ,
149
178
region : Region ,
150
179
}
151
180
@@ -203,8 +232,8 @@ pub struct ExpressionRegion {
203
232
pub struct FunctionCoverage < ' a > {
204
233
source_map : & ' a SourceMap ,
205
234
source_hash : u64 ,
206
- counters : Vec < Option < Region > > ,
207
- expressions : Vec < Option < ExpressionRegion > > ,
235
+ counters : IndexVec < CounterValueReference , Option < Region > > ,
236
+ expressions : IndexVec < InjectedExpressionIndex , Option < ExpressionRegion > > ,
208
237
unreachable_regions : Vec < Region > ,
209
238
}
210
239
@@ -214,8 +243,8 @@ impl<'a> FunctionCoverage<'a> {
214
243
Self {
215
244
source_map : tcx. sess . source_map ( ) ,
216
245
source_hash : 0 , // will be set with the first `add_counter()`
217
- counters : vec ! [ None ; coverageinfo. num_counters as usize ] ,
218
- expressions : vec ! [ None ; coverageinfo. num_expressions as usize ] ,
246
+ counters : IndexVec :: from_elem_n ( None , coverageinfo. num_counters as usize ) ,
247
+ expressions : IndexVec :: from_elem_n ( None , coverageinfo. num_expressions as usize ) ,
219
248
unreachable_regions : Vec :: new ( ) ,
220
249
}
221
250
}
@@ -235,7 +264,7 @@ impl<'a> FunctionCoverage<'a> {
235
264
} else {
236
265
debug_assert_eq ! ( source_hash, self . source_hash) ;
237
266
}
238
- self . counters [ id as usize ]
267
+ self . counters [ CounterValueReference :: from ( id ) ]
239
268
. replace ( Region :: new ( self . source_map , start_byte_pos, end_byte_pos) )
240
269
. expect_none ( "add_counter called with duplicate `id`" ) ;
241
270
}
@@ -263,7 +292,11 @@ impl<'a> FunctionCoverage<'a> {
263
292
start_byte_pos : u32 ,
264
293
end_byte_pos : u32 ,
265
294
) {
266
- let expression_index = self . expression_index ( id_descending_from_max) ;
295
+ let expression_id = ExpressionOperandId :: from ( id_descending_from_max) ;
296
+ let lhs = ExpressionOperandId :: from ( lhs) ;
297
+ let rhs = ExpressionOperandId :: from ( rhs) ;
298
+
299
+ let expression_index = self . expression_index ( expression_id) ;
267
300
self . expressions [ expression_index]
268
301
. replace ( ExpressionRegion {
269
302
lhs,
@@ -294,19 +327,21 @@ impl<'a> FunctionCoverage<'a> {
294
327
assert ! ( self . source_hash != 0 ) ;
295
328
296
329
let counter_regions = self . counter_regions ( ) ;
297
- let ( expressions , expression_regions) = self . expressions_with_regions ( ) ;
330
+ let ( counter_expressions , expression_regions) = self . expressions_with_regions ( ) ;
298
331
let unreachable_regions = self . unreachable_regions ( ) ;
299
332
300
333
let counter_regions =
301
334
counter_regions. chain ( expression_regions. into_iter ( ) . chain ( unreachable_regions) ) ;
302
- ( expressions , counter_regions)
335
+ ( counter_expressions , counter_regions)
303
336
}
304
337
305
338
fn counter_regions ( & ' a self ) -> impl Iterator < Item = ( Counter , & ' a Region ) > {
306
- self . counters . iter ( ) . enumerate ( ) . filter_map ( |( index, entry) | {
339
+ self . counters . iter_enumerated ( ) . filter_map ( |( index, entry) | {
307
340
// Option::map() will return None to filter out missing counters. This may happen
308
341
// if, for example, a MIR-instrumented counter is removed during an optimization.
309
- entry. as_ref ( ) . map ( |region| ( Counter :: counter_value_reference ( index as u32 ) , region) )
342
+ entry. as_ref ( ) . map ( |region| {
343
+ ( Counter :: counter_value_reference ( index as CounterValueReference ) , region)
344
+ } )
310
345
} )
311
346
}
312
347
@@ -315,32 +350,39 @@ impl<'a> FunctionCoverage<'a> {
315
350
) -> ( Vec < CounterExpression > , impl Iterator < Item = ( Counter , & ' a Region ) > ) {
316
351
let mut counter_expressions = Vec :: with_capacity ( self . expressions . len ( ) ) ;
317
352
let mut expression_regions = Vec :: with_capacity ( self . expressions . len ( ) ) ;
318
- let mut new_indexes = vec ! [ u32 :: MAX ; self . expressions. len( ) ] ;
353
+ let mut new_indexes =
354
+ IndexVec :: from_elem_n ( MappedExpressionIndex :: from ( u32:: MAX ) , self . expressions . len ( ) ) ;
355
+ // Note, the initial value shouldn't matter since every index in use in `self.expressions`
356
+ // will be set, and after that, `new_indexes` will only be accessed using those same
357
+ // indexes.
319
358
320
359
// Note that an `ExpressionRegion`s at any given index can include other expressions as
321
360
// operands, but expression operands can only come from the subset of expressions having
322
361
// `expression_index`s lower than the referencing `ExpressionRegion`. Therefore, it is
323
362
// reasonable to look up the new index of an expression operand while the `new_indexes`
324
363
// vector is only complete up to the current `ExpressionIndex`.
325
- let id_to_counter = |new_indexes : & Vec < u32 > , id| {
326
- if id < self . counters . len ( ) as u32 {
327
- self . counters
328
- . get ( id as usize )
329
- . expect ( "id is out of range" )
330
- . as_ref ( )
331
- . map ( |_| Counter :: counter_value_reference ( id) )
332
- } else {
333
- let index = self . expression_index ( id) ;
334
- self . expressions
335
- . get ( index)
336
- . expect ( "id is out of range" )
337
- . as_ref ( )
338
- . map ( |_| Counter :: expression ( new_indexes[ index] ) )
339
- }
340
- } ;
364
+ let id_to_counter =
365
+ |new_indexes : & IndexVec < InjectedExpressionIndex , MappedExpressionIndex > ,
366
+ id : ExpressionOperandId | {
367
+ if id. index ( ) < self . counters . len ( ) {
368
+ let index = CounterValueReference :: from ( id. index ( ) ) ;
369
+ self . counters
370
+ . get ( index)
371
+ . unwrap ( ) // pre-validated
372
+ . as_ref ( )
373
+ . map ( |_| Counter :: counter_value_reference ( index) )
374
+ } else {
375
+ let index = self . expression_index ( id) ;
376
+ self . expressions
377
+ . get ( index)
378
+ . expect ( "expression id is out of range" )
379
+ . as_ref ( )
380
+ . map ( |_| Counter :: expression ( new_indexes[ index] ) )
381
+ }
382
+ } ;
341
383
342
384
for ( original_index, expression_region) in
343
- self . expressions . iter ( ) . enumerate ( ) . filter_map ( |( original_index, entry) | {
385
+ self . expressions . iter_enumerated ( ) . filter_map ( |( original_index, entry) | {
344
386
// Option::map() will return None to filter out missing expressions. This may happen
345
387
// if, for example, a MIR-instrumented expression is removed during an optimization.
346
388
entry. as_ref ( ) . map ( |region| ( original_index, region) )
@@ -356,10 +398,11 @@ impl<'a> FunctionCoverage<'a> {
356
398
{
357
399
// Both operands exist. `Expression` operands exist in `self.expressions` and have
358
400
// been assigned a `new_index`.
359
- let final_expression_index = counter_expressions. len ( ) as u32 ;
401
+ let mapped_expression_index =
402
+ MappedExpressionIndex :: from ( counter_expressions. len ( ) ) ;
360
403
counter_expressions. push ( CounterExpression :: new ( lhs_counter, op, rhs_counter) ) ;
361
- new_indexes[ original_index] = final_expression_index ;
362
- expression_regions. push ( ( Counter :: expression ( final_expression_index ) , region) ) ;
404
+ new_indexes[ original_index] = mapped_expression_index ;
405
+ expression_regions. push ( ( Counter :: expression ( mapped_expression_index ) , region) ) ;
363
406
}
364
407
}
365
408
( counter_expressions, expression_regions. into_iter ( ) )
@@ -369,8 +412,11 @@ impl<'a> FunctionCoverage<'a> {
369
412
self . unreachable_regions . iter ( ) . map ( |region| ( Counter :: zero ( ) , region) )
370
413
}
371
414
372
- fn expression_index ( & self , id_descending_from_max : u32 ) -> usize {
373
- debug_assert ! ( id_descending_from_max as usize >= self . counters. len( ) ) ;
374
- ( u32:: MAX - id_descending_from_max) as usize
415
+ fn expression_index (
416
+ & self ,
417
+ id_descending_from_max : ExpressionOperandId ,
418
+ ) -> InjectedExpressionIndex {
419
+ debug_assert ! ( id_descending_from_max. index( ) >= self . counters. len( ) ) ;
420
+ InjectedExpressionIndex :: from ( u32:: MAX - u32:: from ( id_descending_from_max) )
375
421
}
376
422
}
0 commit comments