diff --git a/lib/cretonne/src/cursor.rs b/lib/cretonne/src/cursor.rs new file mode 100644 index 0000000000..b706531eed --- /dev/null +++ b/lib/cretonne/src/cursor.rs @@ -0,0 +1,105 @@ +//! Cursor library. +//! +//! This module defines cursor data types that can be used for inserting instructions. + +use ir; +use isa::TargetIsa; + +// Re-export these types, anticipating their being moved here. +pub use ir::layout::CursorBase as Cursor; +pub use ir::layout::CursorPosition; +pub use ir::layout::Cursor as LayoutCursor; + +/// Encoding cursor. +/// +/// An `EncCursor` can be used to insert instructions that are immediately assigned an encoding. +/// The cursor holds a mutable reference to the whole function which can be re-borrowed from the +/// public `pos.func` member. +pub struct EncCursor<'f> { + pos: CursorPosition, + built_inst: Option, + pub func: &'f mut ir::Function, + pub isa: &'f TargetIsa, +} + +impl<'f> EncCursor<'f> { + /// Create a new `EncCursor` pointing nowhere. + pub fn new(func: &'f mut ir::Function, isa: &'f TargetIsa) -> EncCursor<'f> { + EncCursor { + pos: CursorPosition::Nowhere, + built_inst: None, + func, + isa, + } + } + + /// Create an instruction builder that will insert an encoded instruction at the current + /// position. + /// + /// The builder will panic if it is used to insert an instruction that can't be encoded for + /// `self.isa`. + pub fn ins(&mut self) -> ir::InsertBuilder<&mut EncCursor<'f>> { + ir::InsertBuilder::new(self) + } + + /// Get the last built instruction. + /// + /// This returns the last instruction that was built using the `ins()` method on this cursor. + /// Panics if no instruction was built. + pub fn built_inst(&self) -> ir::Inst { + self.built_inst.expect("No instruction was inserted") + } + + /// Return an object that can display `inst`. + /// + /// This is a convenience wrapper for the DFG equivalent. + pub fn display_inst(&self, inst: ir::Inst) -> ir::dfg::DisplayInst { + self.func.dfg.display_inst(inst, self.isa) + } +} + +impl<'f> Cursor for EncCursor<'f> { + fn position(&self) -> CursorPosition { + self.pos + } + + fn set_position(&mut self, pos: CursorPosition) { + self.pos = pos + } + + fn layout(&self) -> &ir::Layout { + &self.func.layout + } + + fn layout_mut(&mut self) -> &mut ir::Layout { + &mut self.func.layout + } +} + +impl<'c, 'f> ir::InstInserterBase<'c> for &'c mut EncCursor<'f> { + fn data_flow_graph(&self) -> &ir::DataFlowGraph { + &self.func.dfg + } + + fn data_flow_graph_mut(&mut self) -> &mut ir::DataFlowGraph { + &mut self.func.dfg + } + + fn insert_built_inst(self, + inst: ir::Inst, + ctrl_typevar: ir::Type) + -> &'c mut ir::DataFlowGraph { + // Insert the instruction and remember the reference. + self.insert_inst(inst); + self.built_inst = Some(inst); + + // Assign an encoding. + match self.isa + .encode(&self.func.dfg, &self.func.dfg[inst], ctrl_typevar) { + Ok(e) => *self.func.encodings.ensure(inst) = e, + Err(_) => panic!("can't encode {}", self.display_inst(inst)), + } + + &mut self.func.dfg + } +} diff --git a/lib/cretonne/src/lib.rs b/lib/cretonne/src/lib.rs index 44f469ab4e..b021bf55b2 100644 --- a/lib/cretonne/src/lib.rs +++ b/lib/cretonne/src/lib.rs @@ -34,6 +34,7 @@ pub mod verifier; mod abi; mod constant_hash; mod context; +mod cursor; mod iterators; mod legalizer; mod licm; diff --git a/lib/cretonne/src/regalloc/coalescing.rs b/lib/cretonne/src/regalloc/coalescing.rs index b21175ad87..ac11df3498 100644 --- a/lib/cretonne/src/regalloc/coalescing.rs +++ b/lib/cretonne/src/regalloc/coalescing.rs @@ -5,10 +5,11 @@ //! and inserting copies where necessary such that all values passed to an EBB argument will belong //! to the same virtual register as the EBB argument value itself. +use cursor::{Cursor, EncCursor}; use dbg::DisplayList; use dominator_tree::DominatorTree; use flowgraph::{ControlFlowGraph, BasicBlock}; -use ir::{DataFlowGraph, Layout, Cursor, CursorBase, InstBuilder, ValueDef}; +use ir::{DataFlowGraph, Layout, InstBuilder, ValueDef}; use ir::{Function, Ebb, Inst, Value, ExpandedProgramPoint}; use regalloc::affinity::Affinity; use regalloc::liveness::Liveness; @@ -464,37 +465,26 @@ impl<'a> Context<'a> { argnum: usize, pred_val: Value) -> Value { - let copy; - { - let mut pos = Cursor::new(&mut self.func.layout).at_inst(pred_inst); - copy = self.func.dfg.ins(&mut pos).copy(pred_val); - } - let inst = self.func.dfg.value_def(copy).unwrap_inst(); - let ty = self.func.dfg.value_type(copy); + let mut pos = EncCursor::new(self.func, self.isa).at_inst(pred_inst); + let copy = pos.ins().copy(pred_val); + let inst = pos.built_inst(); dbg!("Inserted {}, before {}: {}", - self.func.dfg.display_inst(inst, self.isa), + pos.display_inst(inst), pred_ebb, - self.func.dfg.display_inst(pred_inst, self.isa)); - - // Give it an encoding. - let encoding = match self.isa.encode(&self.func.dfg, &self.func.dfg[inst], ty) { - Ok(e) => e, - Err(_) => panic!("Can't encode copy.{}", ty), - }; - *self.func.encodings.ensure(inst) = encoding; + pos.display_inst(pred_inst)); // Create a live range for the new value. let affinity = Affinity::new(&self.encinfo - .operand_constraints(encoding) + .operand_constraints(pos.func.encodings[inst]) .expect("Bad copy encoding") .outs [0]); self.liveness.create_dead(copy, inst, affinity); self.liveness - .extend_locally(copy, pred_ebb, pred_inst, &self.func.layout); + .extend_locally(copy, pred_ebb, pred_inst, &pos.func.layout); - self.func.dfg.inst_variable_args_mut(pred_inst)[argnum] = copy; + pos.func.dfg.inst_variable_args_mut(pred_inst)[argnum] = copy; self.split_values.push(copy); copy } @@ -505,39 +495,26 @@ impl<'a> Context<'a> { let new_val = self.func.dfg.replace_ebb_arg(succ_val, ty); // Insert a copy instruction at the top of ebb. - { - let mut pos = Cursor::new(&mut self.func.layout).at_first_inst(ebb); - self.func - .dfg - .ins(&mut pos) - .with_result(succ_val) - .copy(new_val); - } - let inst = self.func.dfg.value_def(succ_val).unwrap_inst(); + let mut pos = EncCursor::new(self.func, self.isa).at_first_inst(ebb); + pos.ins().with_result(succ_val).copy(new_val); + let inst = pos.built_inst(); self.liveness.move_def_locally(succ_val, inst); dbg!("Inserted {}, following {}({}: {})", - self.func.dfg.display_inst(inst, self.isa), + pos.display_inst(inst), ebb, new_val, ty); - // Give it an encoding. - let encoding = match self.isa.encode(&self.func.dfg, &self.func.dfg[inst], ty) { - Ok(e) => e, - Err(_) => panic!("Can't encode copy.{}", ty), - }; - *self.func.encodings.ensure(inst) = encoding; - // Create a live range for the new value. let affinity = Affinity::new(&self.encinfo - .operand_constraints(encoding) + .operand_constraints(pos.func.encodings[inst]) .expect("Bad copy encoding") .outs [0]); self.liveness.create_dead(new_val, ebb, affinity); self.liveness - .extend_locally(new_val, ebb, inst, &self.func.layout); + .extend_locally(new_val, ebb, inst, &pos.func.layout); self.split_values.push(new_val); new_val