From 8390c829d353bf1deca9fe02443b951e75e40191 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Tue, 10 Jan 2017 15:33:03 -0800 Subject: [PATCH] Implement DoubleEndedIterator for the ebb_insts() iterator. Make it possible to iterate backwards over the instructions in an EBB. --- lib/cretonne/src/ir/layout.rs | 38 ++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/lib/cretonne/src/ir/layout.rs b/lib/cretonne/src/ir/layout.rs index cecc8645ef..7f2497df1b 100644 --- a/lib/cretonne/src/ir/layout.rs +++ b/lib/cretonne/src/ir/layout.rs @@ -452,7 +452,8 @@ impl Layout { pub fn ebb_insts<'f>(&'f self, ebb: Ebb) -> Insts<'f> { Insts { layout: self, - next: self.ebbs[ebb].first_inst.wrap(), + head: self.ebbs[ebb].first_inst.wrap(), + tail: self.ebbs[ebb].last_inst.wrap(), } } @@ -535,20 +536,39 @@ struct InstNode { /// Iterate over instructions in an EBB in layout order. See `Layout::ebb_insts()`. pub struct Insts<'f> { layout: &'f Layout, - next: Option, + head: Option, + tail: Option, } impl<'f> Iterator for Insts<'f> { type Item = Inst; fn next(&mut self) -> Option { - match self.next { - Some(inst) => { - self.next = self.layout.insts[inst].next.wrap(); - Some(inst) + let rval = self.head; + if let Some(inst) = rval { + if self.head == self.tail { + self.head = None; + self.tail = None; + } else { + self.head = Some(self.layout.insts[inst].next); } - None => None, } + rval + } +} + +impl<'f> DoubleEndedIterator for Insts<'f> { + fn next_back(&mut self) -> Option { + let rval = self.tail; + if let Some(inst) = rval { + if self.head == self.tail { + self.head = None; + self.tail = None; + } else { + self.tail = Some(self.layout.insts[inst].prev); + } + } + rval } } @@ -1077,6 +1097,10 @@ mod tests { let v: Vec = layout.ebb_insts(e1).collect(); assert_eq!(v, [i1, i2]); + // Test double-ended instruction iterator. + let v: Vec = layout.ebb_insts(e1).rev().collect(); + assert_eq!(v, [i2, i1]); + layout.append_inst(i0, e1); verify(&mut layout, &[(e1, &[i1, i2, i0])]);