1
1
use rustc_index:: vec:: IndexVec ;
2
- use rustc_data_structures:: sync:: { RwLock , MappedReadGuard , ReadGuard } ;
3
2
use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher } ;
4
3
use rustc_serialize:: { Encodable , Encoder , Decodable , Decoder } ;
5
4
use crate :: ich:: StableHashingContext ;
6
- use crate :: mir:: { Body , BasicBlock } ;
5
+ use crate :: mir:: { BasicBlock , BasicBlockData , Body , LocalDecls , Location , Successors } ;
6
+ use rustc_data_structures:: graph:: { self , GraphPredecessors , GraphSuccessors } ;
7
+ use rustc_data_structures:: graph:: dominators:: { dominators, Dominators } ;
8
+ use std:: iter;
9
+ use std:: ops:: { Deref , DerefMut , Index , IndexMut } ;
10
+ use std:: vec:: IntoIter ;
7
11
8
12
#[ derive( Clone , Debug ) ]
9
13
pub struct Cache {
10
- predecessors : RwLock < Option < IndexVec < BasicBlock , Vec < BasicBlock > > > >
14
+ predecessors : Option < IndexVec < BasicBlock , Vec < BasicBlock > > > ,
11
15
}
12
16
13
-
14
17
impl rustc_serialize:: Encodable for Cache {
15
18
fn encode < S : Encoder > ( & self , s : & mut S ) -> Result < ( ) , S :: Error > {
16
19
Encodable :: encode ( & ( ) , s)
@@ -31,39 +34,264 @@ impl<'a> HashStable<StableHashingContext<'a>> for Cache {
31
34
32
35
impl Cache {
33
36
pub fn new ( ) -> Self {
34
- Cache {
35
- predecessors : RwLock :: new ( None )
37
+ Self {
38
+ predecessors : None ,
36
39
}
37
40
}
38
41
39
- pub fn invalidate ( & self ) {
42
+ pub fn invalidate_predecessors ( & mut self ) {
40
43
// FIXME: consider being more fine-grained
41
- * self . predecessors . borrow_mut ( ) = None ;
44
+ self . predecessors = None ;
42
45
}
43
46
44
- pub fn predecessors (
45
- & self ,
46
- body : & Body < ' _ >
47
- ) -> MappedReadGuard < ' _ , IndexVec < BasicBlock , Vec < BasicBlock > > > {
48
- if self . predecessors . borrow ( ) . is_none ( ) {
49
- * self . predecessors . borrow_mut ( ) = Some ( calculate_predecessors ( body) ) ;
47
+ pub fn ensure_predecessors ( & mut self , body : & Body < ' _ > ) {
48
+ if self . predecessors . is_none ( ) {
49
+ let mut result = IndexVec :: from_elem ( vec ! [ ] , body. basic_blocks ( ) ) ;
50
+ for ( bb, data) in body. basic_blocks ( ) . iter_enumerated ( ) {
51
+ if let Some ( ref term) = data. terminator {
52
+ for & tgt in term. successors ( ) {
53
+ result[ tgt] . push ( bb) ;
54
+ }
55
+ }
56
+ }
57
+
58
+ self . predecessors = Some ( result)
50
59
}
60
+ }
61
+
62
+ /// This will recompute the predecessors cache if it is not available
63
+ fn predecessors ( & mut self , body : & Body < ' _ > ) -> & IndexVec < BasicBlock , Vec < BasicBlock > > {
64
+ self . ensure_predecessors ( body) ;
65
+ self . predecessors . as_ref ( ) . unwrap ( )
66
+ }
67
+
68
+ fn unwrap_predecessors_for ( & self , bb : BasicBlock ) -> & [ BasicBlock ] {
69
+ & self . predecessors . as_ref ( ) . unwrap ( ) [ bb]
70
+ }
51
71
52
- ReadGuard :: map ( self . predecessors . borrow ( ) , |p| p. as_ref ( ) . unwrap ( ) )
72
+ fn unwrap_predecessor_locations < ' a > (
73
+ & ' a self ,
74
+ loc : Location ,
75
+ body : & ' a Body < ' a >
76
+ ) -> impl Iterator < Item = Location > + ' a {
77
+ let if_zero_locations = if loc. statement_index == 0 {
78
+ let predecessor_blocks = self . unwrap_predecessors_for ( loc. block ) ;
79
+ let num_predecessor_blocks = predecessor_blocks. len ( ) ;
80
+ Some (
81
+ ( 0 ..num_predecessor_blocks)
82
+ . map ( move |i| predecessor_blocks[ i] )
83
+ . map ( move |bb| body. terminator_loc ( bb) ) ,
84
+ )
85
+ } else {
86
+ None
87
+ } ;
88
+
89
+ let if_not_zero_locations = if loc. statement_index == 0 {
90
+ None
91
+ } else {
92
+ Some ( Location { block : loc. block , statement_index : loc. statement_index - 1 } )
93
+ } ;
94
+
95
+ if_zero_locations. into_iter ( ) . flatten ( ) . chain ( if_not_zero_locations)
96
+ }
97
+
98
+ pub fn basic_blocks_mut < ' a , ' tcx > (
99
+ & mut self ,
100
+ body : & ' a mut Body < ' tcx >
101
+ ) -> & ' a mut IndexVec < BasicBlock , BasicBlockData < ' tcx > > {
102
+ debug ! ( "bbm: Clearing predecessors cache for body at: {:?}" , body. span. data( ) ) ;
103
+ self . invalidate_predecessors ( ) ;
104
+ & mut body. basic_blocks
105
+ }
106
+
107
+ pub fn basic_blocks_and_local_decls_mut < ' a , ' tcx > (
108
+ & mut self ,
109
+ body : & ' a mut Body < ' tcx >
110
+ ) -> ( & ' a mut IndexVec < BasicBlock , BasicBlockData < ' tcx > > , & ' a mut LocalDecls < ' tcx > ) {
111
+ debug ! ( "bbaldm: Clearing predecessors cache for body at: {:?}" , body. span. data( ) ) ;
112
+ self . invalidate_predecessors ( ) ;
113
+ ( & mut body. basic_blocks , & mut body. local_decls )
53
114
}
54
115
}
55
116
56
- fn calculate_predecessors ( body : & Body < ' _ > ) -> IndexVec < BasicBlock , Vec < BasicBlock > > {
57
- let mut result = IndexVec :: from_elem ( vec ! [ ] , body. basic_blocks ( ) ) ;
58
- for ( bb, data) in body. basic_blocks ( ) . iter_enumerated ( ) {
59
- if let Some ( ref term) = data. terminator {
60
- for & tgt in term. successors ( ) {
61
- result[ tgt] . push ( bb) ;
62
- }
117
+ #[ derive( Clone , Debug , HashStable , RustcEncodable , RustcDecodable , TypeFoldable ) ]
118
+ pub struct BodyCache < ' tcx > {
119
+ cache : Cache ,
120
+ body : Body < ' tcx > ,
121
+ }
122
+
123
+ impl BodyCache < ' tcx > {
124
+ pub fn new ( body : Body < ' tcx > ) -> Self {
125
+ Self {
126
+ cache : Cache :: new ( ) ,
127
+ body,
128
+ }
129
+ }
130
+ }
131
+
132
+ #[ macro_export]
133
+ macro_rules! read_only {
134
+ ( $body: expr) => {
135
+ {
136
+ $body. ensure_predecessors( ) ;
137
+ $body. unwrap_read_only( )
138
+ }
139
+ } ;
140
+ }
141
+
142
+ impl BodyCache < ' tcx > {
143
+ pub fn ensure_predecessors ( & mut self ) {
144
+ self . cache . ensure_predecessors ( & self . body ) ;
145
+ }
146
+
147
+ pub fn predecessors ( & mut self ) -> & IndexVec < BasicBlock , Vec < BasicBlock > > {
148
+ self . cache . predecessors ( & self . body )
149
+ }
150
+
151
+ pub fn unwrap_read_only ( & self ) -> ReadOnlyBodyCache < ' _ , ' tcx > {
152
+ ReadOnlyBodyCache :: new ( & self . cache , & self . body )
153
+ }
154
+
155
+ pub fn basic_blocks_mut ( & mut self ) -> & mut IndexVec < BasicBlock , BasicBlockData < ' tcx > > {
156
+ self . cache . basic_blocks_mut ( & mut self . body )
157
+ }
158
+
159
+ pub fn basic_blocks_and_local_decls_mut (
160
+ & mut self
161
+ ) -> ( & mut IndexVec < BasicBlock , BasicBlockData < ' tcx > > , & mut LocalDecls < ' tcx > ) {
162
+ self . cache . basic_blocks_and_local_decls_mut ( & mut self . body )
163
+ }
164
+ }
165
+
166
+ impl < ' tcx > Index < BasicBlock > for BodyCache < ' tcx > {
167
+ type Output = BasicBlockData < ' tcx > ;
168
+
169
+ fn index ( & self , index : BasicBlock ) -> & BasicBlockData < ' tcx > {
170
+ & self . body [ index]
171
+ }
172
+ }
173
+
174
+ impl < ' tcx > IndexMut < BasicBlock > for BodyCache < ' tcx > {
175
+ fn index_mut ( & mut self , index : BasicBlock ) -> & mut Self :: Output {
176
+ & mut self . basic_blocks_mut ( ) [ index]
177
+ }
178
+ }
179
+
180
+ impl < ' tcx > Deref for BodyCache < ' tcx > {
181
+ type Target = Body < ' tcx > ;
182
+
183
+ fn deref ( & self ) -> & Self :: Target {
184
+ & self . body
185
+ }
186
+ }
187
+
188
+ impl < ' tcx > DerefMut for BodyCache < ' tcx > {
189
+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
190
+ & mut self . body
191
+ }
192
+ }
193
+
194
+ #[ derive( Copy , Clone , Debug ) ]
195
+ pub struct ReadOnlyBodyCache < ' a , ' tcx > {
196
+ cache : & ' a Cache ,
197
+ body : & ' a Body < ' tcx > ,
198
+ }
199
+
200
+ impl ReadOnlyBodyCache < ' a , ' tcx > {
201
+ fn new ( cache : & ' a Cache , body : & ' a Body < ' tcx > ) -> Self {
202
+ assert ! (
203
+ cache. predecessors. is_some( ) ,
204
+ "Cannot construct ReadOnlyBodyCache without computed predecessors" ) ;
205
+ Self {
206
+ cache,
207
+ body,
63
208
}
64
209
}
65
210
66
- result
211
+ pub fn predecessors ( & self ) -> & IndexVec < BasicBlock , Vec < BasicBlock > > {
212
+ self . cache . predecessors . as_ref ( ) . unwrap ( )
213
+ }
214
+
215
+ pub fn predecessors_for ( & self , bb : BasicBlock ) -> & [ BasicBlock ] {
216
+ self . cache . unwrap_predecessors_for ( bb)
217
+ }
218
+
219
+ pub fn predecessor_locations ( & self , loc : Location ) -> impl Iterator < Item = Location > + ' _ {
220
+ self . cache . unwrap_predecessor_locations ( loc, self . body )
221
+ }
222
+
223
+ pub fn body ( & self ) -> & ' a Body < ' tcx > {
224
+ self . body
225
+ }
226
+
227
+ pub fn basic_blocks ( & self ) -> & IndexVec < BasicBlock , BasicBlockData < ' tcx > > {
228
+ & self . body . basic_blocks
229
+ }
230
+
231
+ pub fn dominators ( & self ) -> Dominators < BasicBlock > {
232
+ dominators ( self )
233
+ }
234
+ }
235
+
236
+ impl graph:: DirectedGraph for ReadOnlyBodyCache < ' a , ' tcx > {
237
+ type Node = BasicBlock ;
238
+ }
239
+
240
+ impl graph:: GraphPredecessors < ' graph > for ReadOnlyBodyCache < ' a , ' tcx > {
241
+ type Item = BasicBlock ;
242
+ type Iter = IntoIter < BasicBlock > ;
243
+ }
244
+
245
+ impl graph:: WithPredecessors for ReadOnlyBodyCache < ' a , ' tcx > {
246
+ fn predecessors (
247
+ & self ,
248
+ node : Self :: Node ,
249
+ ) -> <Self as GraphPredecessors < ' _ > >:: Iter {
250
+ self . cache . unwrap_predecessors_for ( node) . to_vec ( ) . into_iter ( )
251
+ }
252
+ }
253
+
254
+ impl graph:: WithNumNodes for ReadOnlyBodyCache < ' a , ' tcx > {
255
+ fn num_nodes ( & self ) -> usize {
256
+ self . body . num_nodes ( )
257
+ }
258
+ }
259
+
260
+ impl graph:: WithStartNode for ReadOnlyBodyCache < ' a , ' tcx > {
261
+ fn start_node ( & self ) -> Self :: Node {
262
+ self . body . start_node ( )
263
+ }
264
+ }
265
+
266
+ impl graph:: WithSuccessors for ReadOnlyBodyCache < ' a , ' tcx > {
267
+ fn successors (
268
+ & self ,
269
+ node : Self :: Node ,
270
+ ) -> <Self as GraphSuccessors < ' _ > >:: Iter {
271
+ self . body . successors ( node)
272
+ }
273
+ }
274
+
275
+ impl < ' a , ' b , ' tcx > graph:: GraphSuccessors < ' b > for ReadOnlyBodyCache < ' a , ' tcx > {
276
+ type Item = BasicBlock ;
277
+ type Iter = iter:: Cloned < Successors < ' b > > ;
278
+ }
279
+
280
+
281
+ impl Deref for ReadOnlyBodyCache < ' a , ' tcx > {
282
+ type Target = Body < ' tcx > ;
283
+
284
+ fn deref ( & self ) -> & Self :: Target {
285
+ self . body
286
+ }
287
+ }
288
+
289
+ impl Index < BasicBlock > for ReadOnlyBodyCache < ' a , ' tcx > {
290
+ type Output = BasicBlockData < ' tcx > ;
291
+
292
+ fn index ( & self , index : BasicBlock ) -> & BasicBlockData < ' tcx > {
293
+ & self . body [ index]
294
+ }
67
295
}
68
296
69
297
CloneTypeFoldableAndLiftImpls ! {
0 commit comments