Add support for postorder traversal of the cfg.

This commit is contained in:
Morgan Phillips
2016-07-21 15:22:27 -07:00
parent 30eb25d013
commit 761fb54d8a

View File

@@ -42,6 +42,15 @@ pub struct CFGNode {
pub predecessors: BasicBlockSet, pub predecessors: BasicBlockSet,
} }
impl CFGNode {
/// CFG Node successors stripped of loop edges.
pub fn children(&self) -> Vec<Ebb> {
let pred_ebbs = self.predecessors.iter().map(|&(ebb, _)| { ebb }).collect();
let children = self.successors.difference(&pred_ebbs).cloned().collect();
children
}
}
impl CFGNode { impl CFGNode {
pub fn new() -> CFGNode { pub fn new() -> CFGNode {
CFGNode { CFGNode {
@@ -109,6 +118,26 @@ impl ControlFlowGraph {
&self.data[ebb].successors &self.data[ebb].successors
} }
pub fn get_children(&self, ebb: Ebb) -> Vec<Ebb> {
self.data[ebb].children()
}
pub fn postorder_ebbs(&self) -> Vec<Ebb> {
if self.len() < 1 {
return Vec::new();
}
let mut stack_a = vec![Ebb::with_number(0).unwrap()];
let mut stack_b = Vec::new();
while stack_a.len() > 0 {
let cur = stack_a.pop().unwrap();
for child in self.get_children(cur) {
stack_a.push(child);
}
stack_b.push(cur);
}
stack_b
}
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.data.len() self.data.len()
} }
@@ -228,5 +257,45 @@ mod tests {
assert_eq!(ebb0_successors.contains(&ebb2), true); assert_eq!(ebb0_successors.contains(&ebb2), true);
assert_eq!(ebb1_successors.contains(&ebb1), true); assert_eq!(ebb1_successors.contains(&ebb1), true);
assert_eq!(ebb1_successors.contains(&ebb2), true); assert_eq!(ebb1_successors.contains(&ebb2), true);
assert_eq!(cfg.get_children(ebb0), vec![ebb1, ebb2]);
assert_eq!(cfg.get_children(ebb1), vec![ebb2]);
assert_eq!(cfg.get_children(ebb2), Vec::new());
}
#[test]
fn postorder_traversal() {
let mut func = Function::new();
let ebb0 = func.dfg.make_ebb();
let ebb1 = func.dfg.make_ebb();
let ebb2 = func.dfg.make_ebb();
let ebb3 = func.dfg.make_ebb();
let ebb4 = func.dfg.make_ebb();
let ebb5 = func.dfg.make_ebb();
func.layout.append_ebb(ebb0);
func.layout.append_ebb(ebb1);
func.layout.append_ebb(ebb2);
func.layout.append_ebb(ebb3);
func.layout.append_ebb(ebb4);
func.layout.append_ebb(ebb5);
let br_ebb0_ebb1 = make_inst::branch(&mut func, ebb1);
func.layout.append_inst(br_ebb0_ebb1, ebb0);
let jmp_ebb0_ebb2 = make_inst::jump(&mut func, ebb2);
func.layout.append_inst(jmp_ebb0_ebb2, ebb0);
let jmp_ebb1_ebb3 = make_inst::jump(&mut func, ebb3);
func.layout.append_inst(jmp_ebb1_ebb3, ebb1);
let br_ebb2_ebb4 = make_inst::branch(&mut func, ebb4);
func.layout.append_inst(br_ebb2_ebb4, ebb2);
let jmp_ebb2_ebb5 = make_inst::jump(&mut func, ebb5);
func.layout.append_inst(jmp_ebb2_ebb5, ebb2);
let cfg = ControlFlowGraph::new(&func);
assert_eq!(cfg.postorder_ebbs(), vec![ebb0, ebb2, ebb5, ebb4, ebb1, ebb3]);
} }
} }