@@ -188,10 +188,6 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
188
188
}
189
189
}
190
190
191
- pub fn postorder < ' a , ' tcx > ( body : & ' a Body < ' tcx > ) -> Postorder < ' a , ' tcx > {
192
- Postorder :: new ( & body. basic_blocks , START_BLOCK )
193
- }
194
-
195
191
impl < ' a , ' tcx > Iterator for Postorder < ' a , ' tcx > {
196
192
type Item = ( BasicBlock , & ' a BasicBlockData < ' tcx > ) ;
197
193
@@ -219,6 +215,42 @@ impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> {
219
215
}
220
216
}
221
217
218
+ /// Creates an iterator over the `Body`'s basic blocks, that:
219
+ /// - returns basic blocks in a postorder,
220
+ /// - traverses the `BasicBlocks` CFG cache's reverse postorder backwards, and does not cache the
221
+ /// postorder itself.
222
+ pub fn postorder < ' a , ' tcx > ( body : & ' a Body < ' tcx > ) -> PostorderIter < ' a , ' tcx > {
223
+ let blocks = body. basic_blocks . reverse_postorder ( ) ;
224
+ let len = blocks. len ( ) ;
225
+ PostorderIter { body, blocks, idx : len }
226
+ }
227
+
228
+ #[ derive( Clone ) ]
229
+ pub struct PostorderIter < ' a , ' tcx > {
230
+ body : & ' a Body < ' tcx > ,
231
+ blocks : & ' a [ BasicBlock ] ,
232
+ idx : usize ,
233
+ }
234
+
235
+ impl < ' a , ' tcx > Iterator for PostorderIter < ' a , ' tcx > {
236
+ type Item = ( BasicBlock , & ' a BasicBlockData < ' tcx > ) ;
237
+
238
+ fn next ( & mut self ) -> Option < ( BasicBlock , & ' a BasicBlockData < ' tcx > ) > {
239
+ if self . idx == 0 {
240
+ return None ;
241
+ }
242
+ self . idx -= 1 ;
243
+
244
+ self . blocks . get ( self . idx ) . map ( |& bb| ( bb, & self . body [ bb] ) )
245
+ }
246
+
247
+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
248
+ ( self . idx , Some ( self . idx ) )
249
+ }
250
+ }
251
+
252
+ impl < ' a , ' tcx > ExactSizeIterator for PostorderIter < ' a , ' tcx > { }
253
+
222
254
/// Reverse postorder traversal of a graph
223
255
///
224
256
/// Reverse postorder is the reverse order of a postorder traversal.
0 commit comments