Add a FuncCursor type to the cursor library.
A FuncCursor works a like a layout cursor, but it holds a reference to the entire function and lets you re-borrow the function reference. Rewrite the dominator tree unit tests with a FuncCursor instead of a layout cursor to demonstrate the difference. It avoids the constrained lifetimes of the layout cursor in the tests.
This commit is contained in:
@@ -10,6 +10,67 @@ pub use ir::layout::CursorBase as Cursor;
|
|||||||
pub use ir::layout::CursorPosition;
|
pub use ir::layout::CursorPosition;
|
||||||
pub use ir::layout::Cursor as LayoutCursor;
|
pub use ir::layout::Cursor as LayoutCursor;
|
||||||
|
|
||||||
|
/// Function cursor.
|
||||||
|
///
|
||||||
|
/// A `FuncCursor` holds a mutable reference to a whole `ir::Function` while keeping a position
|
||||||
|
/// too. The function can be re-borrowed by accessing the public `cur.func` member.
|
||||||
|
///
|
||||||
|
/// This cursor is for use before legalization. The inserted instructions are not given an
|
||||||
|
/// encoding.
|
||||||
|
pub struct FuncCursor<'f> {
|
||||||
|
pos: CursorPosition,
|
||||||
|
pub func: &'f mut ir::Function,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'f> FuncCursor<'f> {
|
||||||
|
/// Create a new `FuncCursor` pointing nowhere.
|
||||||
|
pub fn new(func: &'f mut ir::Function) -> FuncCursor<'f> {
|
||||||
|
FuncCursor {
|
||||||
|
pos: CursorPosition::Nowhere,
|
||||||
|
func,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create an instruction builder that inserts an instruction at the current position.
|
||||||
|
pub fn ins(&mut self) -> ir::InsertBuilder<&mut FuncCursor<'f>> {
|
||||||
|
ir::InsertBuilder::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'f> Cursor for FuncCursor<'f> {
|
||||||
|
fn position(&self) -> CursorPosition {
|
||||||
|
self.pos
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_position(&mut self, pos: CursorPosition) {
|
||||||
|
self.pos = pos
|
||||||
|
}
|
||||||
|
|
||||||
|
fn layout(&self) -> &ir::Layout {
|
||||||
|
&self.func.layout
|
||||||
|
}
|
||||||
|
|
||||||
|
fn layout_mut(&mut self) -> &mut ir::Layout {
|
||||||
|
&mut self.func.layout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'c, 'f> ir::InstInserterBase<'c> for &'c mut FuncCursor<'f> {
|
||||||
|
fn data_flow_graph(&self) -> &ir::DataFlowGraph {
|
||||||
|
&self.func.dfg
|
||||||
|
}
|
||||||
|
|
||||||
|
fn data_flow_graph_mut(&mut self) -> &mut ir::DataFlowGraph {
|
||||||
|
&mut self.func.dfg
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert_built_inst(self, inst: ir::Inst, _: ir::Type) -> &'c mut ir::DataFlowGraph {
|
||||||
|
self.insert_inst(inst);
|
||||||
|
&mut self.func.dfg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Encoding cursor.
|
/// Encoding cursor.
|
||||||
///
|
///
|
||||||
/// An `EncCursor` can be used to insert instructions that are immediately assigned an encoding.
|
/// An `EncCursor` can be used to insert instructions that are immediately assigned an encoding.
|
||||||
|
|||||||
@@ -387,8 +387,9 @@ impl DominatorTree {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
use cursor::{Cursor, FuncCursor};
|
||||||
use flowgraph::ControlFlowGraph;
|
use flowgraph::ControlFlowGraph;
|
||||||
use ir::{Function, InstBuilder, Cursor, CursorBase, types};
|
use ir::{Function, InstBuilder, types};
|
||||||
use super::*;
|
use super::*;
|
||||||
use ir::types::*;
|
use ir::types::*;
|
||||||
use verifier::verify_context;
|
use verifier::verify_context;
|
||||||
@@ -411,45 +412,38 @@ mod test {
|
|||||||
let ebb2 = func.dfg.make_ebb();
|
let ebb2 = func.dfg.make_ebb();
|
||||||
let ebb0 = func.dfg.make_ebb();
|
let ebb0 = func.dfg.make_ebb();
|
||||||
|
|
||||||
let jmp_ebb3_ebb1;
|
let mut cur = FuncCursor::new(&mut func);
|
||||||
let br_ebb1_ebb0;
|
|
||||||
let jmp_ebb1_ebb2;
|
|
||||||
|
|
||||||
{
|
cur.insert_ebb(ebb3);
|
||||||
let dfg = &mut func.dfg;
|
let jmp_ebb3_ebb1 = cur.ins().jump(ebb1, &[]);
|
||||||
let cur = &mut Cursor::new(&mut func.layout);
|
|
||||||
|
|
||||||
cur.insert_ebb(ebb3);
|
cur.insert_ebb(ebb1);
|
||||||
jmp_ebb3_ebb1 = dfg.ins(cur).jump(ebb1, &[]);
|
let br_ebb1_ebb0 = cur.ins().brnz(cond, ebb0, &[]);
|
||||||
|
let jmp_ebb1_ebb2 = cur.ins().jump(ebb2, &[]);
|
||||||
|
|
||||||
cur.insert_ebb(ebb1);
|
cur.insert_ebb(ebb2);
|
||||||
br_ebb1_ebb0 = dfg.ins(cur).brnz(cond, ebb0, &[]);
|
cur.ins().jump(ebb0, &[]);
|
||||||
jmp_ebb1_ebb2 = dfg.ins(cur).jump(ebb2, &[]);
|
|
||||||
|
|
||||||
cur.insert_ebb(ebb2);
|
cur.insert_ebb(ebb0);
|
||||||
dfg.ins(cur).jump(ebb0, &[]);
|
|
||||||
|
|
||||||
cur.insert_ebb(ebb0);
|
let cfg = ControlFlowGraph::with_function(cur.func);
|
||||||
}
|
let dt = DominatorTree::with_function(cur.func, &cfg);
|
||||||
|
|
||||||
let cfg = ControlFlowGraph::with_function(&func);
|
assert_eq!(cur.func.layout.entry_block().unwrap(), ebb3);
|
||||||
let dt = DominatorTree::with_function(&func, &cfg);
|
|
||||||
|
|
||||||
assert_eq!(func.layout.entry_block().unwrap(), ebb3);
|
|
||||||
assert_eq!(dt.idom(ebb3), None);
|
assert_eq!(dt.idom(ebb3), None);
|
||||||
assert_eq!(dt.idom(ebb1).unwrap(), jmp_ebb3_ebb1);
|
assert_eq!(dt.idom(ebb1).unwrap(), jmp_ebb3_ebb1);
|
||||||
assert_eq!(dt.idom(ebb2).unwrap(), jmp_ebb1_ebb2);
|
assert_eq!(dt.idom(ebb2).unwrap(), jmp_ebb1_ebb2);
|
||||||
assert_eq!(dt.idom(ebb0).unwrap(), br_ebb1_ebb0);
|
assert_eq!(dt.idom(ebb0).unwrap(), br_ebb1_ebb0);
|
||||||
|
|
||||||
assert!(dt.dominates(br_ebb1_ebb0, br_ebb1_ebb0, &func.layout));
|
assert!(dt.dominates(br_ebb1_ebb0, br_ebb1_ebb0, &cur.func.layout));
|
||||||
assert!(!dt.dominates(br_ebb1_ebb0, jmp_ebb3_ebb1, &func.layout));
|
assert!(!dt.dominates(br_ebb1_ebb0, jmp_ebb3_ebb1, &cur.func.layout));
|
||||||
assert!(dt.dominates(jmp_ebb3_ebb1, br_ebb1_ebb0, &func.layout));
|
assert!(dt.dominates(jmp_ebb3_ebb1, br_ebb1_ebb0, &cur.func.layout));
|
||||||
|
|
||||||
assert_eq!(dt.rpo_cmp(ebb3, ebb3, &func.layout), Ordering::Equal);
|
assert_eq!(dt.rpo_cmp(ebb3, ebb3, &cur.func.layout), Ordering::Equal);
|
||||||
assert_eq!(dt.rpo_cmp(ebb3, ebb1, &func.layout), Ordering::Less);
|
assert_eq!(dt.rpo_cmp(ebb3, ebb1, &cur.func.layout), Ordering::Less);
|
||||||
assert_eq!(dt.rpo_cmp(ebb3, jmp_ebb3_ebb1, &func.layout),
|
assert_eq!(dt.rpo_cmp(ebb3, jmp_ebb3_ebb1, &cur.func.layout),
|
||||||
Ordering::Less);
|
Ordering::Less);
|
||||||
assert_eq!(dt.rpo_cmp(jmp_ebb3_ebb1, jmp_ebb1_ebb2, &func.layout),
|
assert_eq!(dt.rpo_cmp(jmp_ebb3_ebb1, jmp_ebb1_ebb2, &cur.func.layout),
|
||||||
Ordering::Less);
|
Ordering::Less);
|
||||||
|
|
||||||
assert_eq!(dt.cfg_postorder(), &[ebb2, ebb0, ebb1, ebb3]);
|
assert_eq!(dt.cfg_postorder(), &[ebb2, ebb0, ebb1, ebb3]);
|
||||||
@@ -462,72 +456,66 @@ mod test {
|
|||||||
let ebb1 = func.dfg.make_ebb();
|
let ebb1 = func.dfg.make_ebb();
|
||||||
let ebb2 = func.dfg.make_ebb();
|
let ebb2 = func.dfg.make_ebb();
|
||||||
|
|
||||||
let jmp02;
|
let mut cur = FuncCursor::new(&mut func);
|
||||||
let jmp21;
|
|
||||||
let trap;
|
|
||||||
{
|
|
||||||
let dfg = &mut func.dfg;
|
|
||||||
let cur = &mut Cursor::new(&mut func.layout);
|
|
||||||
|
|
||||||
cur.insert_ebb(ebb0);
|
cur.insert_ebb(ebb0);
|
||||||
jmp02 = dfg.ins(cur).jump(ebb2, &[]);
|
let jmp02 = cur.ins().jump(ebb2, &[]);
|
||||||
|
|
||||||
cur.insert_ebb(ebb1);
|
cur.insert_ebb(ebb1);
|
||||||
trap = dfg.ins(cur).trap();
|
let trap = cur.ins().trap();
|
||||||
|
|
||||||
cur.insert_ebb(ebb2);
|
cur.insert_ebb(ebb2);
|
||||||
jmp21 = dfg.ins(cur).jump(ebb1, &[]);
|
let jmp21 = cur.ins().jump(ebb1, &[]);
|
||||||
}
|
|
||||||
|
|
||||||
let cfg = ControlFlowGraph::with_function(&func);
|
let cfg = ControlFlowGraph::with_function(cur.func);
|
||||||
let dt = DominatorTree::with_function(&func, &cfg);
|
let dt = DominatorTree::with_function(cur.func, &cfg);
|
||||||
|
|
||||||
assert_eq!(func.layout.entry_block(), Some(ebb0));
|
assert_eq!(cur.func.layout.entry_block(), Some(ebb0));
|
||||||
assert_eq!(dt.idom(ebb0), None);
|
assert_eq!(dt.idom(ebb0), None);
|
||||||
assert_eq!(dt.idom(ebb1), Some(jmp21));
|
assert_eq!(dt.idom(ebb1), Some(jmp21));
|
||||||
assert_eq!(dt.idom(ebb2), Some(jmp02));
|
assert_eq!(dt.idom(ebb2), Some(jmp02));
|
||||||
|
|
||||||
assert!(dt.dominates(ebb0, ebb0, &func.layout));
|
assert!(dt.dominates(ebb0, ebb0, &cur.func.layout));
|
||||||
assert!(dt.dominates(ebb0, jmp02, &func.layout));
|
assert!(dt.dominates(ebb0, jmp02, &cur.func.layout));
|
||||||
assert!(dt.dominates(ebb0, ebb1, &func.layout));
|
assert!(dt.dominates(ebb0, ebb1, &cur.func.layout));
|
||||||
assert!(dt.dominates(ebb0, trap, &func.layout));
|
assert!(dt.dominates(ebb0, trap, &cur.func.layout));
|
||||||
assert!(dt.dominates(ebb0, ebb2, &func.layout));
|
assert!(dt.dominates(ebb0, ebb2, &cur.func.layout));
|
||||||
assert!(dt.dominates(ebb0, jmp21, &func.layout));
|
assert!(dt.dominates(ebb0, jmp21, &cur.func.layout));
|
||||||
|
|
||||||
assert!(!dt.dominates(jmp02, ebb0, &func.layout));
|
assert!(!dt.dominates(jmp02, ebb0, &cur.func.layout));
|
||||||
assert!(dt.dominates(jmp02, jmp02, &func.layout));
|
assert!(dt.dominates(jmp02, jmp02, &cur.func.layout));
|
||||||
assert!(dt.dominates(jmp02, ebb1, &func.layout));
|
assert!(dt.dominates(jmp02, ebb1, &cur.func.layout));
|
||||||
assert!(dt.dominates(jmp02, trap, &func.layout));
|
assert!(dt.dominates(jmp02, trap, &cur.func.layout));
|
||||||
assert!(dt.dominates(jmp02, ebb2, &func.layout));
|
assert!(dt.dominates(jmp02, ebb2, &cur.func.layout));
|
||||||
assert!(dt.dominates(jmp02, jmp21, &func.layout));
|
assert!(dt.dominates(jmp02, jmp21, &cur.func.layout));
|
||||||
|
|
||||||
assert!(!dt.dominates(ebb1, ebb0, &func.layout));
|
assert!(!dt.dominates(ebb1, ebb0, &cur.func.layout));
|
||||||
assert!(!dt.dominates(ebb1, jmp02, &func.layout));
|
assert!(!dt.dominates(ebb1, jmp02, &cur.func.layout));
|
||||||
assert!(dt.dominates(ebb1, ebb1, &func.layout));
|
assert!(dt.dominates(ebb1, ebb1, &cur.func.layout));
|
||||||
assert!(dt.dominates(ebb1, trap, &func.layout));
|
assert!(dt.dominates(ebb1, trap, &cur.func.layout));
|
||||||
assert!(!dt.dominates(ebb1, ebb2, &func.layout));
|
assert!(!dt.dominates(ebb1, ebb2, &cur.func.layout));
|
||||||
assert!(!dt.dominates(ebb1, jmp21, &func.layout));
|
assert!(!dt.dominates(ebb1, jmp21, &cur.func.layout));
|
||||||
|
|
||||||
assert!(!dt.dominates(trap, ebb0, &func.layout));
|
assert!(!dt.dominates(trap, ebb0, &cur.func.layout));
|
||||||
assert!(!dt.dominates(trap, jmp02, &func.layout));
|
assert!(!dt.dominates(trap, jmp02, &cur.func.layout));
|
||||||
assert!(!dt.dominates(trap, ebb1, &func.layout));
|
assert!(!dt.dominates(trap, ebb1, &cur.func.layout));
|
||||||
assert!(dt.dominates(trap, trap, &func.layout));
|
assert!(dt.dominates(trap, trap, &cur.func.layout));
|
||||||
assert!(!dt.dominates(trap, ebb2, &func.layout));
|
assert!(!dt.dominates(trap, ebb2, &cur.func.layout));
|
||||||
assert!(!dt.dominates(trap, jmp21, &func.layout));
|
assert!(!dt.dominates(trap, jmp21, &cur.func.layout));
|
||||||
|
|
||||||
assert!(!dt.dominates(ebb2, ebb0, &func.layout));
|
assert!(!dt.dominates(ebb2, ebb0, &cur.func.layout));
|
||||||
assert!(!dt.dominates(ebb2, jmp02, &func.layout));
|
assert!(!dt.dominates(ebb2, jmp02, &cur.func.layout));
|
||||||
assert!(dt.dominates(ebb2, ebb1, &func.layout));
|
assert!(dt.dominates(ebb2, ebb1, &cur.func.layout));
|
||||||
assert!(dt.dominates(ebb2, trap, &func.layout));
|
assert!(dt.dominates(ebb2, trap, &cur.func.layout));
|
||||||
assert!(dt.dominates(ebb2, ebb2, &func.layout));
|
assert!(dt.dominates(ebb2, ebb2, &cur.func.layout));
|
||||||
assert!(dt.dominates(ebb2, jmp21, &func.layout));
|
assert!(dt.dominates(ebb2, jmp21, &cur.func.layout));
|
||||||
|
|
||||||
assert!(!dt.dominates(jmp21, ebb0, &func.layout));
|
assert!(!dt.dominates(jmp21, ebb0, &cur.func.layout));
|
||||||
assert!(!dt.dominates(jmp21, jmp02, &func.layout));
|
assert!(!dt.dominates(jmp21, jmp02, &cur.func.layout));
|
||||||
assert!(dt.dominates(jmp21, ebb1, &func.layout));
|
assert!(dt.dominates(jmp21, ebb1, &cur.func.layout));
|
||||||
assert!(dt.dominates(jmp21, trap, &func.layout));
|
assert!(dt.dominates(jmp21, trap, &cur.func.layout));
|
||||||
assert!(!dt.dominates(jmp21, ebb2, &func.layout));
|
assert!(!dt.dominates(jmp21, ebb2, &cur.func.layout));
|
||||||
assert!(dt.dominates(jmp21, jmp21, &func.layout));
|
assert!(dt.dominates(jmp21, jmp21, &cur.func.layout));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -536,63 +524,47 @@ mod test {
|
|||||||
let ebb0 = func.dfg.make_ebb();
|
let ebb0 = func.dfg.make_ebb();
|
||||||
let ebb100 = func.dfg.make_ebb();
|
let ebb100 = func.dfg.make_ebb();
|
||||||
|
|
||||||
let inst2;
|
let mut cur = FuncCursor::new(&mut func);
|
||||||
let inst3;
|
|
||||||
let inst4;
|
|
||||||
let inst5;
|
|
||||||
{
|
|
||||||
let dfg = &mut func.dfg;
|
|
||||||
let cur = &mut Cursor::new(&mut func.layout);
|
|
||||||
|
|
||||||
cur.insert_ebb(ebb0);
|
cur.insert_ebb(ebb0);
|
||||||
let cond = dfg.ins(cur).iconst(I32, 0);
|
let cond = cur.ins().iconst(I32, 0);
|
||||||
inst2 = dfg.ins(cur).brz(cond, ebb0, &[]);
|
let inst2 = cur.ins().brz(cond, ebb0, &[]);
|
||||||
inst3 = dfg.ins(cur).brz(cond, ebb0, &[]);
|
let inst3 = cur.ins().brz(cond, ebb0, &[]);
|
||||||
inst4 = dfg.ins(cur).brz(cond, ebb0, &[]);
|
let inst4 = cur.ins().brz(cond, ebb0, &[]);
|
||||||
inst5 = dfg.ins(cur).brz(cond, ebb0, &[]);
|
let inst5 = cur.ins().brz(cond, ebb0, &[]);
|
||||||
dfg.ins(cur).jump(ebb100, &[]);
|
cur.ins().jump(ebb100, &[]);
|
||||||
cur.insert_ebb(ebb100);
|
cur.insert_ebb(ebb100);
|
||||||
dfg.ins(cur).return_(&[]);
|
cur.ins().return_(&[]);
|
||||||
}
|
|
||||||
let mut cfg = ControlFlowGraph::with_function(&func);
|
let mut cfg = ControlFlowGraph::with_function(cur.func);
|
||||||
let mut dt = DominatorTree::with_function(&func, &cfg);
|
let mut dt = DominatorTree::with_function(cur.func, &cfg);
|
||||||
|
|
||||||
|
let ebb1 = cur.func.dfg.make_ebb();
|
||||||
|
cur.func.layout.split_ebb(ebb1, inst2);
|
||||||
|
cur.goto_bottom(ebb0);
|
||||||
|
let middle_jump_inst = cur.ins().jump(ebb1, &[]);
|
||||||
|
|
||||||
let ebb1 = func.dfg.make_ebb();
|
|
||||||
func.layout.split_ebb(ebb1, inst2);
|
|
||||||
let middle_jump_inst = {
|
|
||||||
let cur = &mut Cursor::new(&mut func.layout);
|
|
||||||
cur.goto_bottom(ebb0);
|
|
||||||
func.dfg.ins(cur).jump(ebb1, &[])
|
|
||||||
};
|
|
||||||
dt.recompute_split_ebb(ebb0, ebb1, middle_jump_inst);
|
dt.recompute_split_ebb(ebb0, ebb1, middle_jump_inst);
|
||||||
|
|
||||||
let ebb2 = func.dfg.make_ebb();
|
let ebb2 = cur.func.dfg.make_ebb();
|
||||||
func.layout.split_ebb(ebb2, inst3);
|
cur.func.layout.split_ebb(ebb2, inst3);
|
||||||
let middle_jump_inst = {
|
cur.goto_bottom(ebb1);
|
||||||
let cur = &mut Cursor::new(&mut func.layout);
|
let middle_jump_inst = cur.ins().jump(ebb2, &[]);
|
||||||
cur.goto_bottom(ebb1);
|
|
||||||
func.dfg.ins(cur).jump(ebb2, &[])
|
|
||||||
};
|
|
||||||
dt.recompute_split_ebb(ebb1, ebb2, middle_jump_inst);
|
dt.recompute_split_ebb(ebb1, ebb2, middle_jump_inst);
|
||||||
|
|
||||||
let ebb3 = func.dfg.make_ebb();
|
let ebb3 = cur.func.dfg.make_ebb();
|
||||||
func.layout.split_ebb(ebb3, inst4);
|
cur.func.layout.split_ebb(ebb3, inst4);
|
||||||
let middle_jump_inst = {
|
cur.goto_bottom(ebb2);
|
||||||
let cur = &mut Cursor::new(&mut func.layout);
|
let middle_jump_inst = cur.ins().jump(ebb3, &[]);
|
||||||
cur.goto_bottom(ebb2);
|
|
||||||
func.dfg.ins(cur).jump(ebb3, &[])
|
|
||||||
};
|
|
||||||
dt.recompute_split_ebb(ebb2, ebb3, middle_jump_inst);
|
dt.recompute_split_ebb(ebb2, ebb3, middle_jump_inst);
|
||||||
|
|
||||||
let ebb4 = func.dfg.make_ebb();
|
let ebb4 = cur.func.dfg.make_ebb();
|
||||||
func.layout.split_ebb(ebb4, inst5);
|
cur.func.layout.split_ebb(ebb4, inst5);
|
||||||
let middle_jump_inst = {
|
cur.goto_bottom(ebb3);
|
||||||
let cur = &mut Cursor::new(&mut func.layout);
|
let middle_jump_inst = cur.ins().jump(ebb4, &[]);
|
||||||
cur.goto_bottom(ebb3);
|
|
||||||
func.dfg.ins(cur).jump(ebb4, &[])
|
|
||||||
};
|
|
||||||
dt.recompute_split_ebb(ebb3, ebb4, middle_jump_inst);
|
dt.recompute_split_ebb(ebb3, ebb4, middle_jump_inst);
|
||||||
cfg.compute(&func);
|
|
||||||
verify_context(&func, &cfg, &dt, None).unwrap();
|
cfg.compute(cur.func);
|
||||||
|
verify_context(cur.func, &cfg, &dt, None).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user