From 8fb8a41f8ecd256d1d42005af3c942ca4146e0db Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Fri, 14 Oct 2016 15:02:58 -0700 Subject: [PATCH] Give Builder a Cursor. The Builder keeps track of a position in the layout and inserts new instructions there. Add insert_ebb() and ebb() methods to Builder. Use Builder in the cfg tests. --- cranelift/src/libcretonne/cfg.rs | 32 ++++++++++++++----------- cranelift/src/libcretonne/ir/builder.rs | 32 +++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 16 deletions(-) diff --git a/cranelift/src/libcretonne/cfg.rs b/cranelift/src/libcretonne/cfg.rs index 8397ca5166..aab576ae82 100644 --- a/cranelift/src/libcretonne/cfg.rs +++ b/cranelift/src/libcretonne/cfg.rs @@ -139,9 +139,7 @@ impl ControlFlowGraph { #[cfg(test)] mod tests { use super::*; - use ir::Function; - - use test_utils::make_inst; + use ir::{Function, Builder, Cursor, VariableArgs, types}; #[test] fn empty() { @@ -176,23 +174,29 @@ mod tests { fn branches_and_jumps() { let mut func = Function::new(); let ebb0 = func.dfg.make_ebb(); + let cond = func.dfg.append_ebb_arg(ebb0, types::I32); let ebb1 = func.dfg.make_ebb(); let ebb2 = func.dfg.make_ebb(); - func.layout.append_ebb(ebb0); - func.layout.append_ebb(ebb1); - func.layout.append_ebb(ebb2); - let br_ebb0_ebb2 = make_inst::branch(&mut func, ebb2); - func.layout.append_inst(br_ebb0_ebb2, ebb0); + let br_ebb0_ebb2; + let br_ebb1_ebb1; + let jmp_ebb0_ebb1; + let jmp_ebb1_ebb2; - let jmp_ebb0_ebb1 = make_inst::jump(&mut func, ebb1); - func.layout.append_inst(jmp_ebb0_ebb1, ebb0); + { + let mut cursor = Cursor::new(&mut func.layout); + let mut b = Builder::new(&mut func.dfg, &mut cursor); - let br_ebb1_ebb1 = make_inst::branch(&mut func, ebb1); - func.layout.append_inst(br_ebb1_ebb1, ebb1); + b.insert_ebb(ebb0); + br_ebb0_ebb2 = b.brnz(cond, ebb2, VariableArgs::new()); + jmp_ebb0_ebb1 = b.jump(ebb1, VariableArgs::new()); - let jmp_ebb1_ebb2 = make_inst::jump(&mut func, ebb2); - func.layout.append_inst(jmp_ebb1_ebb2, ebb1); + b.insert_ebb(ebb1); + br_ebb1_ebb1 = b.brnz(cond, ebb1, VariableArgs::new()); + jmp_ebb1_ebb2 = b.jump(ebb2, VariableArgs::new()); + + b.insert_ebb(ebb2); + } let cfg = ControlFlowGraph::new(&func); diff --git a/cranelift/src/libcretonne/ir/builder.rs b/cranelift/src/libcretonne/ir/builder.rs index 4e81027e9b..e31be0f2ca 100644 --- a/cranelift/src/libcretonne/ir/builder.rs +++ b/cranelift/src/libcretonne/ir/builder.rs @@ -4,20 +4,48 @@ //! function. Many of its methods are generated from the meta language instruction definitions. use ir::{types, instructions}; -use ir::{InstructionData, DataFlowGraph}; +use ir::{InstructionData, DataFlowGraph, Cursor}; use ir::{Opcode, Type, Inst, Value, Ebb, JumpTable, VariableArgs, FuncRef}; use ir::immediates::{Imm64, Uimm8, Ieee32, Ieee64, ImmVector}; use ir::condcodes::{IntCC, FloatCC}; +/// Instruction builder. +/// +/// A `Builder` holds mutable references to a data flow graph and a layout cursor. It provides +/// convenience method for creating and inserting instructions at the current cursor position. pub struct Builder<'a> { - dfg: &'a mut DataFlowGraph, + pub dfg: &'a mut DataFlowGraph, + pub pos: &'a mut Cursor<'a>, } impl<'a> Builder<'a> { + /// Create a new builder which inserts instructions at `pos`. + /// The `dfg` and `pos.layout` references should be from the same `Function`. + pub fn new(dfg: &'a mut DataFlowGraph, pos: &'a mut Cursor<'a>) -> Builder<'a> { + Builder { + dfg: dfg, + pos: pos, + } + } + + /// Create and insert an EBB. Further instructions will be inserted into the new EBB. + pub fn ebb(&mut self) -> Ebb { + let ebb = self.dfg.make_ebb(); + self.insert_ebb(ebb); + ebb + } + + /// Insert an existing EBB at the current position. Further instructions will be inserted into + /// the new EBB. + pub fn insert_ebb(&mut self, ebb: Ebb) { + self.pos.insert_ebb(ebb); + } + // Create and insert an instruction. // This method is used by the generated format-specific methods. fn insert_inst(&mut self, data: InstructionData) -> Inst { let inst = self.dfg.make_inst(data); + self.pos.insert_inst(inst); inst } }