1+ use rustc_index:: vec:: IndexVec ;
12use rustc_middle:: ty:: Instance ;
23use rustc_middle:: ty:: TyCtxt ;
34use rustc_span:: source_map:: { Pos , SourceMap } ;
@@ -7,6 +8,34 @@ use std::cmp::{Ord, Ordering};
78use std:: fmt;
89use std:: path:: PathBuf ;
910
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+
1039/// 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)
1140#[ derive( Copy , Clone , Debug ) ]
1241#[ repr( C ) ]
@@ -38,12 +67,12 @@ impl Counter {
3867 Self { kind : CounterKind :: Zero , id : 0 }
3968 }
4069
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 ( ) }
4372 }
4473
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 ( ) }
4776 }
4877}
4978
@@ -143,9 +172,9 @@ impl Region {
143172
144173#[ derive( Clone , Debug ) ]
145174pub struct ExpressionRegion {
146- lhs : u32 ,
175+ lhs : ExpressionOperandId ,
147176 op : ExprKind ,
148- rhs : u32 ,
177+ rhs : ExpressionOperandId ,
149178 region : Region ,
150179}
151180
@@ -203,8 +232,8 @@ pub struct ExpressionRegion {
203232pub struct FunctionCoverage < ' a > {
204233 source_map : & ' a SourceMap ,
205234 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 > > ,
208237 unreachable_regions : Vec < Region > ,
209238}
210239
@@ -214,8 +243,8 @@ impl<'a> FunctionCoverage<'a> {
214243 Self {
215244 source_map : tcx. sess . source_map ( ) ,
216245 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 ) ,
219248 unreachable_regions : Vec :: new ( ) ,
220249 }
221250 }
@@ -235,7 +264,7 @@ impl<'a> FunctionCoverage<'a> {
235264 } else {
236265 debug_assert_eq ! ( source_hash, self . source_hash) ;
237266 }
238- self . counters [ id as usize ]
267+ self . counters [ CounterValueReference :: from ( id ) ]
239268 . replace ( Region :: new ( self . source_map , start_byte_pos, end_byte_pos) )
240269 . expect_none ( "add_counter called with duplicate `id`" ) ;
241270 }
@@ -263,7 +292,11 @@ impl<'a> FunctionCoverage<'a> {
263292 start_byte_pos : u32 ,
264293 end_byte_pos : u32 ,
265294 ) {
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) ;
267300 self . expressions [ expression_index]
268301 . replace ( ExpressionRegion {
269302 lhs,
@@ -294,19 +327,21 @@ impl<'a> FunctionCoverage<'a> {
294327 assert ! ( self . source_hash != 0 ) ;
295328
296329 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 ( ) ;
298331 let unreachable_regions = self . unreachable_regions ( ) ;
299332
300333 let counter_regions =
301334 counter_regions. chain ( expression_regions. into_iter ( ) . chain ( unreachable_regions) ) ;
302- ( expressions , counter_regions)
335+ ( counter_expressions , counter_regions)
303336 }
304337
305338 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) | {
307340 // Option::map() will return None to filter out missing counters. This may happen
308341 // 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+ } )
310345 } )
311346 }
312347
@@ -315,32 +350,39 @@ impl<'a> FunctionCoverage<'a> {
315350 ) -> ( Vec < CounterExpression > , impl Iterator < Item = ( Counter , & ' a Region ) > ) {
316351 let mut counter_expressions = Vec :: with_capacity ( self . expressions . len ( ) ) ;
317352 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.
319358
320359 // Note that an `ExpressionRegion`s at any given index can include other expressions as
321360 // operands, but expression operands can only come from the subset of expressions having
322361 // `expression_index`s lower than the referencing `ExpressionRegion`. Therefore, it is
323362 // reasonable to look up the new index of an expression operand while the `new_indexes`
324363 // 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+ } ;
341383
342384 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) | {
344386 // Option::map() will return None to filter out missing expressions. This may happen
345387 // if, for example, a MIR-instrumented expression is removed during an optimization.
346388 entry. as_ref ( ) . map ( |region| ( original_index, region) )
@@ -356,10 +398,11 @@ impl<'a> FunctionCoverage<'a> {
356398 {
357399 // Both operands exist. `Expression` operands exist in `self.expressions` and have
358400 // 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 ( ) ) ;
360403 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) ) ;
363406 }
364407 }
365408 ( counter_expressions, expression_regions. into_iter ( ) )
@@ -369,8 +412,11 @@ impl<'a> FunctionCoverage<'a> {
369412 self . unreachable_regions . iter ( ) . map ( |region| ( Counter :: zero ( ) , region) )
370413 }
371414
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) )
375421 }
376422}
0 commit comments