More layout tests and bugfixes.

Fix bugs in append methods. Linked lists are hard.
This commit is contained in:
Jakob Stoklund Olesen
2016-07-18 18:09:31 -07:00
parent 21c2474d4d
commit 2f74efd5fc

View File

@@ -67,14 +67,18 @@ impl Layout {
pub fn append_ebb(&mut self, ebb: Ebb) { pub fn append_ebb(&mut self, ebb: Ebb) {
assert!(!self.is_ebb_inserted(ebb), assert!(!self.is_ebb_inserted(ebb),
"Cannot append EBB that is already in the layout"); "Cannot append EBB that is already in the layout");
{
let node = &mut self.ebbs[ebb]; let node = &mut self.ebbs[ebb];
assert!(node.first_inst == NO_INST && node.last_inst == NO_INST); assert!(node.first_inst == NO_INST && node.last_inst == NO_INST);
node.prev = self.last_ebb.unwrap_or_default(); node.prev = self.last_ebb.unwrap_or_default();
node.next = NO_EBB; node.next = NO_EBB;
self.last_ebb = Some(ebb); }
if self.first_ebb.is_none() { if let Some(last) = self.last_ebb {
self.ebbs[last].next = ebb;
} else {
self.first_ebb = Some(ebb); self.first_ebb = Some(ebb);
} }
self.last_ebb = Some(ebb);
} }
/// Insert `ebb` in the layout before the existing EBB `before`. /// Insert `ebb` in the layout before the existing EBB `before`.
@@ -151,13 +155,18 @@ impl Layout {
assert!(self.is_ebb_inserted(ebb), assert!(self.is_ebb_inserted(ebb),
"Cannot append instructions to EBB not in layout"); "Cannot append instructions to EBB not in layout");
let ebb_node = &mut self.ebbs[ebb]; let ebb_node = &mut self.ebbs[ebb];
{
let inst_node = &mut self.insts[inst]; let inst_node = &mut self.insts[inst];
inst_node.ebb = ebb; inst_node.ebb = ebb;
inst_node.prev = ebb_node.last_inst; inst_node.prev = ebb_node.last_inst;
assert_eq!(inst_node.next, NO_INST); assert_eq!(inst_node.next, NO_INST);
}
if ebb_node.first_inst == NO_INST { if ebb_node.first_inst == NO_INST {
ebb_node.first_inst = inst; ebb_node.first_inst = inst;
} else {
self.insts[ebb_node.last_inst].next = inst;
} }
ebb_node.last_inst = inst;
} }
/// Insert `inst` before the instruction `before` in the same EBB. /// Insert `inst` before the instruction `before` in the same EBB.
@@ -222,6 +231,44 @@ mod tests {
use entity_map::EntityRef; use entity_map::EntityRef;
use entities::{Ebb, Inst}; use entities::{Ebb, Inst};
#[test]
fn append_ebb() {
let mut layout = Layout::new();
let e0 = Ebb::new(0);
let e1 = Ebb::new(1);
let e2 = Ebb::new(2);
{
let imm = &layout;
assert!(!imm.is_ebb_inserted(e0));
assert!(!imm.is_ebb_inserted(e1));
let v: Vec<Ebb> = layout.ebbs().collect();
assert_eq!(v, []);
}
layout.append_ebb(e1);
assert!(!layout.is_ebb_inserted(e0));
assert!(layout.is_ebb_inserted(e1));
assert!(!layout.is_ebb_inserted(e2));
let v: Vec<Ebb> = layout.ebbs().collect();
assert_eq!(v, [e1]);
layout.append_ebb(e2);
assert!(!layout.is_ebb_inserted(e0));
assert!(layout.is_ebb_inserted(e1));
assert!(layout.is_ebb_inserted(e2));
let v: Vec<Ebb> = layout.ebbs().collect();
assert_eq!(v, [e1, e2]);
layout.append_ebb(e0);
assert!(layout.is_ebb_inserted(e0));
assert!(layout.is_ebb_inserted(e1));
assert!(layout.is_ebb_inserted(e2));
let v: Vec<Ebb> = layout.ebbs().collect();
assert_eq!(v, [e1, e2, e0]);
}
#[test] #[test]
fn insert_ebb() { fn insert_ebb() {
let mut layout = Layout::new(); let mut layout = Layout::new();
@@ -260,6 +307,45 @@ mod tests {
assert_eq!(v, [e2, e0, e1]); assert_eq!(v, [e2, e0, e1]);
} }
#[test]
fn append_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.append_inst(i2, e1);
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, [i1, i2]);
layout.append_inst(i0, e1);
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, [i1, i2, i0]);
}
#[test] #[test]
fn insert_inst() { fn insert_inst() {
let mut layout = Layout::new(); let mut layout = Layout::new();
@@ -298,4 +384,30 @@ mod tests {
let v: Vec<Inst> = layout.ebb_insts(e1).collect(); let v: Vec<Inst> = layout.ebb_insts(e1).collect();
assert_eq!(v, [i2, i0, i1]); assert_eq!(v, [i2, i0, i1]);
} }
#[test]
fn multiple_ebbs() {
let mut layout = Layout::new();
let e0 = Ebb::new(0);
let e1 = Ebb::new(1);
layout.append_ebb(e0);
layout.append_ebb(e1);
let i0 = Inst::new(0);
let i1 = Inst::new(1);
let i2 = Inst::new(2);
let i3 = Inst::new(3);
layout.append_inst(i0, e0);
layout.append_inst(i1, e0);
layout.append_inst(i2, e1);
layout.append_inst(i3, e1);
let v0: Vec<Inst> = layout.ebb_insts(e0).collect();
let v1: Vec<Inst> = layout.ebb_insts(e1).collect();
assert_eq!(v0, [i0, i1]);
assert_eq!(v1, [i2, i3]);
}
} }