Implement DoubleEndedIterator for the ebb_insts() iterator.

Make it possible to iterate backwards over the instructions in an EBB.
This commit is contained in:
Jakob Stoklund Olesen
2017-01-10 15:33:03 -08:00
parent 29777e26ee
commit 8390c829d3

View File

@@ -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<Inst>,
head: Option<Inst>,
tail: Option<Inst>,
}
impl<'f> Iterator for Insts<'f> {
type Item = Inst;
fn next(&mut self) -> Option<Inst> {
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<Inst> {
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<Inst> = layout.ebb_insts(e1).collect();
assert_eq!(v, [i1, i2]);
// Test double-ended instruction iterator.
let v: Vec<Inst> = layout.ebb_insts(e1).rev().collect();
assert_eq!(v, [i2, i1]);
layout.append_inst(i0, e1);
verify(&mut layout, &[(e1, &[i1, i2, i0])]);