diff --git a/src/libcretonne/cfg.rs b/src/libcretonne/cfg.rs index 964a07a572..e221f55fcd 100644 --- a/src/libcretonne/cfg.rs +++ b/src/libcretonne/cfg.rs @@ -24,7 +24,7 @@ use ir::Function; use ir::entities::{Inst, Ebb}; -use ir::instructions::InstructionData; +use ir::instructions::BranchInfo; use entity_map::EntityMap; /// A basic block denoted by its enclosing Ebb and last instruction. @@ -68,16 +68,18 @@ impl ControlFlowGraph { for ebb in &func.layout { for inst in func.layout.ebb_insts(ebb) { - match func.dfg[inst] { - InstructionData::Branch { ty: _, opcode: _, ref data } => { - cfg.add_successor(ebb, data.destination); - cfg.add_predecessor(data.destination, (ebb, inst)); + match func.dfg[inst].analyze_branch() { + BranchInfo::SingleDest(dest, _) => { + cfg.add_successor(ebb, dest); + cfg.add_predecessor(dest, (ebb, inst)); } - InstructionData::Jump { ty: _, opcode: _, ref data } => { - cfg.add_successor(ebb, data.destination); - cfg.add_predecessor(data.destination, (ebb, inst)); + BranchInfo::Table(jt) => { + for (_, dest) in func.jump_tables[jt].entries() { + cfg.add_successor(ebb, dest); + cfg.add_predecessor(dest, (ebb, inst)); + } } - _ => (), + BranchInfo::NotABranch => {} } } } diff --git a/src/libcretonne/ir/instructions.rs b/src/libcretonne/ir/instructions.rs index a6c7bd03f1..4087e246d5 100644 --- a/src/libcretonne/ir/instructions.rs +++ b/src/libcretonne/ir/instructions.rs @@ -344,6 +344,42 @@ impl InstructionData { } } +/// Analyzing an instruction. +/// +/// Avoid large matches on instruction formats by using the methods efined here to examine +/// instructions. +impl InstructionData { + /// Return information about the destination of a branch or jump instruction. + /// + /// Any instruction that can transfer control to another EBB reveals its possible destinations + /// here. + pub fn analyze_branch<'a>(&'a self) -> BranchInfo<'a> { + match self { + &InstructionData::Jump { ref data, .. } => { + BranchInfo::SingleDest(data.destination, &data.arguments) + } + &InstructionData::Branch { ref data, .. } => { + BranchInfo::SingleDest(data.destination, &data.arguments) + } + &InstructionData::BranchTable { table, .. } => BranchInfo::Table(table), + _ => BranchInfo::NotABranch, + } + } +} + +/// Information about branch and jump instructions. +pub enum BranchInfo<'a> { + /// This is not a branch or jump instruction. + /// This instruction will not transfer control to another EBB in the function, but it may still + /// affect control flow by returning or trapping. + NotABranch, + + /// This is a branch or jump to a single destination EBB, possibly taking value arguments. + SingleDest(Ebb, &'a [Value]), + + /// This is a jump table branch which can have many destination EBBs. + Table(JumpTable), +} /// Value type constraints for a given opcode. ///