Implement instruction order.
Each EBB has a linked list of instructions in layout order.
This commit is contained in:
@@ -139,32 +139,53 @@ impl Layout {
|
||||
/// Get the EBB containing `inst`, or `None` if `inst` is not inserted in the layout.
|
||||
pub fn inst_ebb(&self, inst: Inst) -> Option<Ebb> {
|
||||
if self.insts.is_valid(inst) {
|
||||
let ebb = self.insts[inst].ebb;
|
||||
if ebb == NO_EBB {
|
||||
None
|
||||
} else {
|
||||
Some(ebb)
|
||||
}
|
||||
self.insts[inst].ebb.wrap()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Append `inst` to the end of `ebb`.
|
||||
pub fn append_inst(&self, inst: Inst, ebb: Ebb) {
|
||||
pub fn append_inst(&mut self, inst: Inst, ebb: Ebb) {
|
||||
assert_eq!(self.inst_ebb(inst), None);
|
||||
assert!(self.is_ebb_inserted(ebb),
|
||||
"Cannot append instructions to EBB not in layout");
|
||||
unimplemented!();
|
||||
let ebb_node = &mut self.ebbs[ebb];
|
||||
let inst_node = &mut self.insts[inst];
|
||||
inst_node.ebb = ebb;
|
||||
inst_node.prev = ebb_node.last_inst;
|
||||
assert_eq!(inst_node.next, NO_INST);
|
||||
if ebb_node.first_inst == NO_INST {
|
||||
ebb_node.first_inst = inst;
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert `inst` before the instruction `before` in the same EBB.
|
||||
pub fn insert_inst(&self, inst: Inst, before: Inst) {
|
||||
pub fn insert_inst(&mut self, inst: Inst, before: Inst) {
|
||||
assert_eq!(self.inst_ebb(inst), None);
|
||||
let ebb = self.inst_ebb(before)
|
||||
.expect("Instruction before insertion point not in the layout");
|
||||
assert!(ebb != NO_EBB);
|
||||
unimplemented!();
|
||||
let after = self.insts[before].prev;
|
||||
{
|
||||
let inst_node = &mut self.insts[inst];
|
||||
inst_node.ebb = ebb;
|
||||
inst_node.next = before;
|
||||
inst_node.prev = after;
|
||||
}
|
||||
self.insts[before].prev = inst;
|
||||
if after == NO_INST {
|
||||
self.ebbs[ebb].first_inst = inst;
|
||||
} else {
|
||||
self.insts[after].next = inst;
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterate over the instructions in `ebb` in layout order.
|
||||
pub fn ebb_insts<'a>(&'a self, ebb: Ebb) -> Insts<'a> {
|
||||
Insts {
|
||||
layout: self,
|
||||
next: self.ebbs[ebb].first_inst.wrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,11 +196,31 @@ struct InstNode {
|
||||
next: Inst,
|
||||
}
|
||||
|
||||
/// Iterate over instructions in an EBB in layout order. See `Layout::ebb_insts()`.
|
||||
pub struct Insts<'a> {
|
||||
layout: &'a Layout,
|
||||
next: Option<Inst>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Insts<'a> {
|
||||
type Item = Inst;
|
||||
|
||||
fn next(&mut self) -> Option<Inst> {
|
||||
match self.next {
|
||||
Some(inst) => {
|
||||
self.next = self.layout.insts[inst].next.wrap();
|
||||
Some(inst)
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Layout;
|
||||
use entity_map::EntityRef;
|
||||
use entities::Ebb;
|
||||
use entities::{Ebb, Inst};
|
||||
|
||||
#[test]
|
||||
fn insert_ebb() {
|
||||
@@ -218,4 +259,43 @@ mod tests {
|
||||
let v: Vec<Ebb> = layout.ebbs().collect();
|
||||
assert_eq!(v, [e2, e0, e1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_inst() {
|
||||
let mut layout = Layout::new();
|
||||
let e1 = Ebb::new(1);
|
||||
|
||||
layout.append_ebb(e1);
|
||||
let v: Vec<Inst> = layout.ebb_insts(e1).collect();
|
||||
assert_eq!(v, []);
|
||||
|
||||
let i0 = Inst::new(0);
|
||||
let i1 = Inst::new(1);
|
||||
let i2 = Inst::new(2);
|
||||
|
||||
assert_eq!(layout.inst_ebb(i0), None);
|
||||
assert_eq!(layout.inst_ebb(i1), None);
|
||||
assert_eq!(layout.inst_ebb(i2), None);
|
||||
|
||||
layout.append_inst(i1, e1);
|
||||
assert_eq!(layout.inst_ebb(i0), None);
|
||||
assert_eq!(layout.inst_ebb(i1), Some(e1));
|
||||
assert_eq!(layout.inst_ebb(i2), None);
|
||||
let v: Vec<Inst> = layout.ebb_insts(e1).collect();
|
||||
assert_eq!(v, [i1]);
|
||||
|
||||
layout.insert_inst(i2, i1);
|
||||
assert_eq!(layout.inst_ebb(i0), None);
|
||||
assert_eq!(layout.inst_ebb(i1), Some(e1));
|
||||
assert_eq!(layout.inst_ebb(i2), Some(e1));
|
||||
let v: Vec<Inst> = layout.ebb_insts(e1).collect();
|
||||
assert_eq!(v, [i2, i1]);
|
||||
|
||||
layout.insert_inst(i0, i1);
|
||||
assert_eq!(layout.inst_ebb(i0), Some(e1));
|
||||
assert_eq!(layout.inst_ebb(i1), Some(e1));
|
||||
assert_eq!(layout.inst_ebb(i2), Some(e1));
|
||||
let v: Vec<Inst> = layout.ebb_insts(e1).collect();
|
||||
assert_eq!(v, [i2, i0, i1]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user