@ -50,31 +50,44 @@ pub struct ControlFlowGraph {
}
}
impl ControlFlowGraph {
impl ControlFlowGraph {
/// During initialization mappings will be generated for any existing
/// Allocate a new blank control flow graph.
/// blocks within the CFG's associated function.
pub fn new ( ) -> ControlFlowGraph {
pub fn new ( func : & Function ) -> ControlFlowGraph {
ControlFlowGraph {
entry_block : None ,
data : EntityMap ::new ( ) ,
}
}
let mut cfg = ControlFlowGraph {
/// Allocate and compute the control flow graph for `func`.
data : EntityMap ::with_capacity ( func . dfg . num_ebbs ( ) ) ,
pub fn with_function ( func : & Function ) -> ControlFlowGraph {
entry_block : func . layout . entry_block ( ) ,
let mut cfg = ControlFlowGraph ::new ( ) ;
} ;
cfg . compute ( func ) ;
cfg
}
/// Compute the control flow graph of `func`.
///
/// This will clear and overwrite any information already stored in this data structure.
pub fn compute ( & mut self , func : & Function ) {
self . entry_block = func . layout . entry_block ( ) ;
self . data . clear ( ) ;
self . data . resize ( func . dfg . num_ebbs ( ) ) ;
for ebb in & func . layout {
for ebb in & func . layout {
for inst in func . layout . ebb_insts ( ebb ) {
for inst in func . layout . ebb_insts ( ebb ) {
match func . dfg [ inst ] . analyze_branch ( ) {
match func . dfg [ inst ] . analyze_branch ( ) {
BranchInfo ::SingleDest ( dest , _ ) = > {
BranchInfo ::SingleDest ( dest , _ ) = > {
cfg . add_edge ( ( ebb , inst ) , dest ) ;
self . add_edge ( ( ebb , inst ) , dest ) ;
}
}
BranchInfo ::Table ( jt ) = > {
BranchInfo ::Table ( jt ) = > {
for ( _ , dest ) in func . jump_tables [ jt ] . entries ( ) {
for ( _ , dest ) in func . jump_tables [ jt ] . entries ( ) {
cfg . add_edge ( ( ebb , inst ) , dest ) ;
self . add_edge ( ( ebb , inst ) , dest ) ;
}
}
}
}
BranchInfo ::NotABranch = > { }
BranchInfo ::NotABranch = > { }
}
}
}
}
}
}
cfg
}
}
fn add_edge ( & mut self , from : BasicBlock , to : Ebb ) {
fn add_edge ( & mut self , from : BasicBlock , to : Ebb ) {
@ -140,7 +153,7 @@ mod tests {
#[ test ]
#[ test ]
fn empty ( ) {
fn empty ( ) {
let func = Function ::new ( ) ;
let func = Function ::new ( ) ;
let cfg = ControlFlowGraph ::ne w( & func ) ;
let cfg = ControlFlowGraph ::with_function ( & func ) ;
assert_eq ! ( None , cfg . ebbs ( ) . next ( ) ) ;
assert_eq ! ( None , cfg . ebbs ( ) . next ( ) ) ;
}
}
@ -154,7 +167,7 @@ mod tests {
func . layout . append_ebb ( ebb1 ) ;
func . layout . append_ebb ( ebb1 ) ;
func . layout . append_ebb ( ebb2 ) ;
func . layout . append_ebb ( ebb2 ) ;
let cfg = ControlFlowGraph ::ne w( & func ) ;
let cfg = ControlFlowGraph ::with_function ( & func ) ;
let nodes = cfg . ebbs ( ) . collect ::< Vec < _ > > ( ) ;
let nodes = cfg . ebbs ( ) . collect ::< Vec < _ > > ( ) ;
assert_eq ! ( nodes . len ( ) , 3 ) ;
assert_eq ! ( nodes . len ( ) , 3 ) ;
@ -194,7 +207,7 @@ mod tests {
cur . insert_ebb ( ebb2 ) ;
cur . insert_ebb ( ebb2 ) ;
}
}
let cfg = ControlFlowGraph ::ne w( & func ) ;
let cfg = ControlFlowGraph ::with_function ( & func ) ;
let ebb0_predecessors = cfg . get_predecessors ( ebb0 ) ;
let ebb0_predecessors = cfg . get_predecessors ( ebb0 ) ;
let ebb1_predecessors = cfg . get_predecessors ( ebb1 ) ;
let ebb1_predecessors = cfg . get_predecessors ( ebb1 ) ;