1
+ // Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2
+ // file at the top-level directory of this distribution and at
3
+ // http://rust-lang.org/COPYRIGHT.
4
+ //
5
+ // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6
+ // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7
+ // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8
+ // option. This file may not be copied, modified, or distributed
9
+ // except according to those terms.
10
+
1
11
use std:: rc:: Rc ;
2
12
use rustc_data_structures:: bitvec:: BitMatrix ;
3
13
use rustc_data_structures:: indexed_vec:: Idx ;
4
- use rustc:: mir:: Location ;
14
+ use rustc_data_structures:: indexed_vec:: IndexVec ;
15
+ use rustc:: mir:: { BasicBlock , Location , Mir } ;
5
16
use rustc:: ty:: RegionVid ;
6
17
7
18
/// Maps between the various kinds of elements of a region value to
8
19
/// the internal indices that w use.
9
20
pub ( super ) struct RegionValueElements {
10
- points : Vec < Location > ,
21
+ /// For each basic block, how many points are contained within?
22
+ statements_before_block : IndexVec < BasicBlock , usize > ,
23
+ num_points : usize ,
11
24
num_universal_regions : usize ,
12
25
}
13
26
14
27
impl RegionValueElements {
15
- pub ( super ) fn new ( points : Vec < Location > , num_universal_regions : usize ) -> Self {
28
+ pub ( super ) fn new ( mir : & Mir < ' _ > , num_universal_regions : usize ) -> Self {
29
+ let mut num_points = 0 ;
30
+ let statements_before_block =
31
+ mir. basic_blocks ( )
32
+ . iter ( )
33
+ . map ( |block_data| {
34
+ let v = num_points;
35
+ num_points += block_data. statements . len ( ) + 1 ;
36
+ v
37
+ } )
38
+ . collect ( ) ;
39
+
40
+ debug ! ( "RegionValueElements(num_universal_regions={:?})" , num_universal_regions) ;
41
+ debug ! ( "RegionValueElements: statements_before_block={:#?}" , statements_before_block) ;
42
+ debug ! ( "RegionValueElements: num_points={:#?}" , num_points) ;
43
+
16
44
Self {
17
- points ,
45
+ statements_before_block ,
18
46
num_universal_regions,
47
+ num_points,
19
48
}
20
49
}
21
50
51
+ /// Total number of element indices that exist.
52
+ pub ( super ) fn num_elements ( & self ) -> usize {
53
+ self . num_points + self . num_universal_regions
54
+ }
55
+
22
56
/// Converts an element of a region value into a `RegionElementIndex`.
23
57
pub ( super ) fn index < T : ToElementIndex > ( & self , elem : T ) -> RegionElementIndex {
24
58
elem. to_element_index ( self )
25
59
}
26
60
27
61
/// Iterates over the `RegionElementIndex` for all points in the CFG.
28
62
pub ( super ) fn all_point_indices < ' a > ( & ' a self ) -> impl Iterator < Item = RegionElementIndex > + ' a {
29
- ( 0 ..self . points . len ( ) ) . map ( move |i| RegionElementIndex :: new ( i + self . num_universal_regions ) )
63
+ ( 0 ..self . num_points ) . map ( move |i| RegionElementIndex :: new ( i + self . num_universal_regions ) )
30
64
}
31
65
32
66
/// Iterates over the `RegionElementIndex` for all points in the CFG.
@@ -36,10 +70,42 @@ impl RegionValueElements {
36
70
37
71
/// Converts a particular `RegionElementIndex` to the `RegionElement` it represents.
38
72
pub ( super ) fn to_element ( & self , i : RegionElementIndex ) -> RegionElement {
73
+ debug ! ( "to_element(i={:?})" , i) ;
74
+
39
75
if let Some ( r) = self . to_universal_region ( i) {
40
76
RegionElement :: UniversalRegion ( r)
41
77
} else {
42
- RegionElement :: Location ( self . points [ i. index ( ) - self . num_universal_regions ] )
78
+ let point_index = i. index ( ) - self . num_universal_regions ;
79
+
80
+ // Find the basic block. We have a vector with the
81
+ // starting index of the statement in each block. Imagine
82
+ // we have statement #22, and we have a vector like:
83
+ //
84
+ // [0, 10, 20]
85
+ //
86
+ // In that case, this represents point_index 2 of
87
+ // basic block BB2. We know this because BB0 accounts for
88
+ // 0..10, BB1 accounts for 11..20, and BB2 accounts for
89
+ // 20...
90
+ //
91
+ // To compute this, we could do a binary search, but
92
+ // because I am lazy we instead iterate through to find
93
+ // the last point where the "first index" (0, 10, or 20)
94
+ // was less than the statement index (22). In our case, this will
95
+ // be (BB2, 20).
96
+ //
97
+ // Nit: we could do a binary search here but I'm too lazy.
98
+ let ( block, & first_index) =
99
+ self . statements_before_block
100
+ . iter_enumerated ( )
101
+ . filter ( |( _, first_index) | * * first_index <= point_index)
102
+ . last ( )
103
+ . unwrap ( ) ;
104
+
105
+ RegionElement :: Location ( Location {
106
+ block,
107
+ statement_index : point_index - first_index,
108
+ } )
43
109
}
44
110
}
45
111
@@ -85,8 +151,9 @@ pub(super) trait ToElementIndex {
85
151
86
152
impl ToElementIndex for Location {
87
153
fn to_element_index ( self , elements : & RegionValueElements ) -> RegionElementIndex {
88
- let index = elements. points . binary_search ( & self ) . unwrap ( ) ;
89
- RegionElementIndex :: new ( index + elements. num_universal_regions )
154
+ let Location { block, statement_index } = self ;
155
+ let start_index = elements. statements_before_block [ block] ;
156
+ RegionElementIndex :: new ( elements. num_universal_regions + start_index + statement_index)
90
157
}
91
158
}
92
159
@@ -120,11 +187,9 @@ impl RegionValues {
120
187
"universal regions are a subset of the region variables"
121
188
) ;
122
189
123
- let num_columns = elements. points . len ( ) + elements. num_universal_regions ;
124
-
125
190
Self {
126
191
elements : elements. clone ( ) ,
127
- matrix : BitMatrix :: new ( num_region_variables, num_columns ) ,
192
+ matrix : BitMatrix :: new ( num_region_variables, elements . num_elements ( ) ) ,
128
193
}
129
194
}
130
195
0 commit comments