diff --git a/cranelift/src/libcretonne/cfg.rs b/cranelift/src/libcretonne/cfg.rs index 668f5b51ef..af877f4f9b 100644 --- a/cranelift/src/libcretonne/cfg.rs +++ b/cranelift/src/libcretonne/cfg.rs @@ -55,7 +55,7 @@ impl ControlFlowGraph { for ebb in func.ebbs_numerically() { // Flips to true when a terminating instruction is seen. So that if additional // instructions occur an error may be returned. - for inst in func.ebb_insts(ebb) { + for inst in func.layout.ebb_insts(ebb) { match func[inst] { InstructionData::Branch { ty: _, opcode: _, ref data } => { cfg.add_predecessor(data.destination, (ebb, inst)); @@ -109,9 +109,13 @@ mod tests { #[test] fn no_predecessors() { let mut func = Function::new(); - func.make_ebb(); - func.make_ebb(); - func.make_ebb(); + let ebb0 = func.make_ebb(); + let ebb1 = func.make_ebb(); + let ebb2 = func.make_ebb(); + func.layout.append_ebb(ebb0); + func.layout.append_ebb(ebb1); + func.layout.append_ebb(ebb2); + let cfg = ControlFlowGraph::new(&func); let nodes = cfg.iter().collect::>(); assert_eq!(nodes.len(), 3); @@ -129,18 +133,21 @@ mod tests { let ebb0 = func.make_ebb(); let ebb1 = func.make_ebb(); let ebb2 = func.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.append_inst(ebb0, br_ebb0_ebb2); + func.layout.append_inst(br_ebb0_ebb2, ebb0); let jmp_ebb0_ebb1 = make_inst::jump(&mut func, ebb1); - func.append_inst(ebb0, jmp_ebb0_ebb1); + func.layout.append_inst(jmp_ebb0_ebb1, ebb0); let br_ebb1_ebb1 = make_inst::branch(&mut func, ebb1); - func.append_inst(ebb1, br_ebb1_ebb1); + func.layout.append_inst(br_ebb1_ebb1, ebb1); let jmp_ebb1_ebb2 = make_inst::jump(&mut func, ebb2); - func.append_inst(ebb1, jmp_ebb1_ebb2); + func.layout.append_inst(jmp_ebb1_ebb2, ebb1); let cfg = ControlFlowGraph::new(&func); let ebb0_predecessors = cfg.get_predecessors(ebb0).unwrap(); diff --git a/cranelift/src/libcretonne/repr.rs b/cranelift/src/libcretonne/repr.rs index 27de00ea66..ac47a540fe 100644 --- a/cranelift/src/libcretonne/repr.rs +++ b/cranelift/src/libcretonne/repr.rs @@ -2,9 +2,10 @@ use types::{Type, FunctionName, Signature, VOID}; use entity_map::EntityRef; -use entities::{Ebb, NO_EBB, Inst, NO_INST, Value, NO_VALUE, ExpandedValue, StackSlot}; +use entities::{Ebb, NO_EBB, Inst, Value, NO_VALUE, ExpandedValue, StackSlot}; use instructions::*; -use std::fmt::{self, Display, Formatter}; +use layout::Layout; +use std::fmt::{self, Debug, Display, Formatter}; use std::ops::{Index, IndexMut}; /// A function. @@ -12,7 +13,6 @@ use std::ops::{Index, IndexMut}; /// The `Function` struct owns all of its instructions and extended basic blocks, and it works as a /// container for those objects by implementing both `Index` and `Index`. /// -#[derive(Debug)] pub struct Function { /// Name of this function. Mostly used by `.cton` files. pub name: FunctionName, @@ -38,9 +38,8 @@ pub struct Function { /// Others index into this table. extended_values: Vec, - // Linked list nodes for the layout order of instructions. Forms a double linked list per EBB, - // terminated in both ends by NO_INST. - inst_order: Vec, + /// Layout of EBBs and instructions in the function body. + pub layout: Layout, } impl Function { @@ -54,7 +53,7 @@ impl Function { instructions: Vec::new(), extended_basic_blocks: Vec::new(), extended_values: Vec::new(), - inst_order: Vec::new(), + layout: Layout::new(), } } @@ -94,11 +93,6 @@ impl Function { pub fn make_inst(&mut self, data: InstructionData) -> Inst { let inst = Inst::new(self.instructions.len()); self.instructions.push(data); - self.inst_order.push(InstNode { - prev: NO_INST, - next: NO_INST, - }); - debug_assert_eq!(self.instructions.len(), self.inst_order.len()); inst } @@ -234,32 +228,6 @@ impl Function { } } - /// Append an instruction to a basic block. - pub fn append_inst(&mut self, ebb: Ebb, inst: Inst) { - let old_last = self[ebb].last_inst; - - self.inst_order[inst.index()] = InstNode { - prev: old_last, - next: NO_INST, - }; - - if old_last == NO_INST { - assert!(self[ebb].first_inst == NO_INST); - self[ebb].first_inst = inst; - } else { - self.inst_order[old_last.index()].next = inst; - } - self[ebb].last_inst = inst; - } - - /// Iterate through the instructions in `ebb`. - pub fn ebb_insts<'a>(&'a self, ebb: Ebb) -> EbbInsts<'a> { - EbbInsts { - func: self, - cur: self[ebb].first_inst, - } - } - // Values. /// Allocate an extended value entry. @@ -286,6 +254,13 @@ impl Function { } } +impl Debug for Function { + fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { + use write::function_to_string; + fmt.write_str(&function_to_string(self)) + } +} + // ====--------------------------------------------------------------------------------------====// // // Stack slot implementation. @@ -362,12 +337,6 @@ pub struct EbbData { /// Last argument to this EBB, or `NO_VALUE` if the block has no arguments. last_arg: Value, - - /// First instruction in this block, or `NO_INST`. - first_inst: Inst, - - /// Last instruction in this block, or `NO_INST`. - last_inst: Inst, } impl EbbData { @@ -375,8 +344,6 @@ impl EbbData { EbbData { first_arg: NO_VALUE, last_arg: NO_VALUE, - first_inst: NO_INST, - last_inst: NO_INST, } } } @@ -395,26 +362,6 @@ impl IndexMut for Function { } } -pub struct EbbInsts<'a> { - func: &'a Function, - cur: Inst, -} - -impl<'a> Iterator for EbbInsts<'a> { - type Item = Inst; - - fn next(&mut self) -> Option { - let prev = self.cur; - if prev == NO_INST { - None - } else { - // Advance self.cur to the next inst. - self.cur = self.func.inst_order[prev.index()].next; - Some(prev) - } - } -} - /// Iterate through all EBBs in a function in numerical order. /// This order is stable, but has little significance to the semantics of the function. pub struct NumericalEbbs { @@ -460,13 +407,6 @@ impl IndexMut for Function { } } -/// A node in a double linked list of instructions is a basic block. -#[derive(Debug)] -struct InstNode { - prev: Inst, - next: Inst, -} - // ====--------------------------------------------------------------------------------------====// // // Value implementation. @@ -590,6 +530,7 @@ mod tests { let ebb = func.make_ebb(); assert_eq!(ebb.to_string(), "ebb0"); assert_eq!(func.ebb_args(ebb).next(), None); + func.layout.append_ebb(ebb); let arg1 = func.append_ebb_arg(ebb, types::F32); assert_eq!(arg1.to_string(), "vx0"); @@ -612,33 +553,29 @@ mod tests { assert_eq!(ebbs.next(), Some(ebb)); assert_eq!(ebbs.next(), None); - assert_eq!(func.ebb_insts(ebb).next(), None); + assert_eq!(func.layout.ebb_insts(ebb).next(), None); let inst = func.make_inst(InstructionData::Nullary { opcode: Opcode::Iconst, ty: types::I32, }); - func.append_inst(ebb, inst); + func.layout.append_inst(inst, ebb); { - let mut ii = func.ebb_insts(ebb); + let mut ii = func.layout.ebb_insts(ebb); assert_eq!(ii.next(), Some(inst)); assert_eq!(ii.next(), None); } - assert_eq!(func[ebb].first_inst, inst); - assert_eq!(func[ebb].last_inst, inst); let inst2 = func.make_inst(InstructionData::Nullary { opcode: Opcode::Iconst, ty: types::I32, }); - func.append_inst(ebb, inst2); + func.layout.append_inst(inst2, ebb); { - let mut ii = func.ebb_insts(ebb); + let mut ii = func.layout.ebb_insts(ebb); assert_eq!(ii.next(), Some(inst)); assert_eq!(ii.next(), Some(inst2)); assert_eq!(ii.next(), None); } - assert_eq!(func[ebb].first_inst, inst); - assert_eq!(func[ebb].last_inst, inst2); } } diff --git a/cranelift/src/libcretonne/write.rs b/cranelift/src/libcretonne/write.rs index e49956970a..73cb341d96 100644 --- a/cranelift/src/libcretonne/write.rs +++ b/cranelift/src/libcretonne/write.rs @@ -114,7 +114,7 @@ pub fn write_ebb_header(w: &mut Write, func: &Function, ebb: Ebb) -> Result { pub fn write_ebb(w: &mut Write, func: &Function, ebb: Ebb) -> Result { try!(write_ebb_header(w, func, ebb)); - for inst in func.ebb_insts(ebb) { + for inst in func.layout.ebb_insts(ebb) { try!(write_instruction(w, func, inst)); } Ok(()) @@ -251,6 +251,7 @@ mod tests { "function foo() {\n ss0 = stack_slot 4\n}\n"); let ebb = f.make_ebb(); + f.layout.append_ebb(ebb); assert_eq!(function_to_string(&f), "function foo() {\n ss0 = stack_slot 4\n\nebb0:\n}\n"); diff --git a/cranelift/src/libreader/parser.rs b/cranelift/src/libreader/parser.rs index 34dd15f735..2ba382871d 100644 --- a/cranelift/src/libreader/parser.rs +++ b/cranelift/src/libreader/parser.rs @@ -101,6 +101,7 @@ impl Context { // Allocate a new EBB and add a mapping src_ebb -> Ebb. fn add_ebb(&mut self, src_ebb: Ebb, loc: &Location) -> Result { let ebb = self.function.make_ebb(); + self.function.layout.append_ebb(ebb); if self.ebbs.insert(src_ebb, ebb).is_some() { err!(loc, "duplicate EBB: {}", src_ebb) } else { @@ -704,7 +705,7 @@ impl<'a> Parser<'a> { let ctrl_typevar = try!(self.infer_typevar(ctx, opcode, explicit_ctrl_type, &inst_data)); let inst = ctx.function.make_inst(inst_data); let num_results = ctx.function.make_inst_results(inst, ctrl_typevar); - ctx.function.append_inst(ebb, inst); + ctx.function.layout.append_inst(inst, ebb); ctx.add_inst_loc(inst, &opcode_loc); if results.len() != num_results { diff --git a/cranelift/src/tools/print_cfg.rs b/cranelift/src/tools/print_cfg.rs index 002c206e07..6fe51f47e1 100644 --- a/cranelift/src/tools/print_cfg.rs +++ b/cranelift/src/tools/print_cfg.rs @@ -29,7 +29,11 @@ struct CFGPrinter { impl CFGPrinter { pub fn new(writer: T) -> CFGPrinter { - CFGPrinter{level: 0, writer: writer, buffer: String::new()} + CFGPrinter { + level: 0, + writer: writer, + buffer: String::new(), + } } pub fn print(&mut self, func: &Function) -> Result<(), String> { @@ -58,7 +62,7 @@ impl CFGPrinter { fn append(&mut self, s: &str) { let mut indent = String::new(); - for _ in 0 .. self.level { + for _ in 0..self.level { indent = indent + " "; } self.buffer.push_str(&(indent + s)); @@ -103,23 +107,24 @@ impl CFGPrinter { fn ebb_subgraphs(&mut self, func: &Function) { for ebb in func.ebbs_numerically() { - let inst_data = func.ebb_insts(ebb) + let inst_data = func.layout + .ebb_insts(ebb) .filter(|inst| { match func[*inst] { - InstructionData::Branch{ ty: _, opcode: _, data: _ } => true, - InstructionData::Jump{ ty: _, opcode: _, data: _ } => true, - _ => false + InstructionData::Branch { ty: _, opcode: _, data: _ } => true, + InstructionData::Jump { ty: _, opcode: _, data: _ } => true, + _ => false, } }) .map(|inst| { let op = match func[inst] { - InstructionData::Branch{ ty: _, opcode, ref data } => { + InstructionData::Branch { ty: _, opcode, ref data } => { Some((opcode, data.destination)) - }, - InstructionData::Jump{ ty: _, opcode, ref data } => { + } + InstructionData::Jump { ty: _, opcode, ref data } => { Some((opcode, data.destination)) - }, - _ => None + } + _ => None, }; (inst, op) }) @@ -132,7 +137,10 @@ impl CFGPrinter { } self.append(&format!("{} [shape=record, label=\"{}{}{}\"]", - ebb, "{", insts.join(" | "), "}")); + ebb, + "{", + insts.join(" | "), + "}")); self.newline(); } } @@ -145,7 +153,6 @@ impl CFGPrinter { } } } - } fn print_cfg(filename: String) -> CommandResult {