Browse Source

Implement instruction order.

Each EBB has a linked list of instructions in layout order.
pull/3/head
Jakob Stoklund Olesen 8 years ago
parent
commit
21c2474d4d
  1. 104
      src/libcretonne/layout.rs

104
src/libcretonne/layout.rs

@ -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]);
}
}

Loading…
Cancel
Save