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.
|
/// Get the EBB containing `inst`, or `None` if `inst` is not inserted in the layout.
|
||||||
pub fn inst_ebb(&self, inst: Inst) -> Option<Ebb> {
|
pub fn inst_ebb(&self, inst: Inst) -> Option<Ebb> {
|
||||||
if self.insts.is_valid(inst) {
|
if self.insts.is_valid(inst) {
|
||||||
let ebb = self.insts[inst].ebb;
|
self.insts[inst].ebb.wrap()
|
||||||
if ebb == NO_EBB {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(ebb)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Append `inst` to the end of `ebb`.
|
/// 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_eq!(self.inst_ebb(inst), None);
|
||||||
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");
|
||||||
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.
|
/// 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);
|
assert_eq!(self.inst_ebb(inst), None);
|
||||||
let ebb = self.inst_ebb(before)
|
let ebb = self.inst_ebb(before)
|
||||||
.expect("Instruction before insertion point not in the layout");
|
.expect("Instruction before insertion point not in the layout");
|
||||||
assert!(ebb != NO_EBB);
|
let after = self.insts[before].prev;
|
||||||
unimplemented!();
|
{
|
||||||
|
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,
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::Layout;
|
use super::Layout;
|
||||||
use entity_map::EntityRef;
|
use entity_map::EntityRef;
|
||||||
use entities::Ebb;
|
use entities::{Ebb, Inst};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn insert_ebb() {
|
fn insert_ebb() {
|
||||||
@@ -218,4 +259,43 @@ mod tests {
|
|||||||
let v: Vec<Ebb> = layout.ebbs().collect();
|
let v: Vec<Ebb> = layout.ebbs().collect();
|
||||||
assert_eq!(v, [e2, e0, e1]);
|
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