11use rustc_index:: vec:: IndexVec ;
2- use rustc_data_structures:: sync:: { RwLock , MappedReadGuard , ReadGuard } ;
32use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher } ;
43use rustc_serialize:: { Encodable , Encoder , Decodable , Decoder } ;
54use 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 ;
711
812#[ derive( Clone , Debug ) ]
913pub struct Cache {
10- predecessors : RwLock < Option < IndexVec < BasicBlock , Vec < BasicBlock > > > >
14+ predecessors : Option < IndexVec < BasicBlock , Vec < BasicBlock > > > ,
1115}
1216
13-
1417impl rustc_serialize:: Encodable for Cache {
1518 fn encode < S : Encoder > ( & self , s : & mut S ) -> Result < ( ) , S :: Error > {
1619 Encodable :: encode ( & ( ) , s)
@@ -31,39 +34,264 @@ impl<'a> HashStable<StableHashingContext<'a>> for Cache {
3134
3235impl Cache {
3336 pub fn new ( ) -> Self {
34- Cache {
35- predecessors : RwLock :: new ( None )
37+ Self {
38+ predecessors : None ,
3639 }
3740 }
3841
39- pub fn invalidate ( & self ) {
42+ pub fn invalidate_predecessors ( & mut self ) {
4043 // FIXME: consider being more fine-grained
41- * self . predecessors . borrow_mut ( ) = None ;
44+ self . predecessors = None ;
4245 }
4346
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)
5059 }
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+ }
5171
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 )
53114 }
54115}
55116
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,
63208 }
64209 }
65210
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+ }
67295}
68296
69297CloneTypeFoldableAndLiftImpls ! {
0 commit comments