use crate::ir::*; use falcon::{graph, il}; use serde::{Deserialize, Serialize}; use std::fmt; #[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub struct Block { index: usize, instructions: Vec>, } impl Block { pub fn from_il(block: &il::Block) -> Block { Block { index: block.index(), instructions: block .instructions() .iter() .map(|instruction| Instruction::::from_il(instruction)) .collect::>>(), } } /// Find the next instruction index, which is one more than the greatest fn next_index(&self) -> usize { let highest_index = self .instructions() .iter() .map(|instruction| instruction.index()) .max() .unwrap_or(0); highest_index + 1 } pub fn index(&self) -> usize { self.index } pub fn instruction(&self, index: usize) -> Option<&Instruction> { self.instructions() .iter() .find(|instruction| instruction.index() == index) } pub fn instruction_mut(&mut self, index: usize) -> Option<&mut Instruction> { self.instructions_mut() .iter_mut() .find(|instruction| instruction.index() == index) } pub fn instructions(&self) -> &[Instruction] { &self.instructions } pub fn instructions_mut(&mut self) -> &mut [Instruction] { &mut self.instructions } pub fn replace_with_nop(&mut self, index: usize) -> Result<()> { let instruction = match self.instruction_mut(index) { Some(instruction) => instruction, None => bail!("Invalid index for Block::replace_with_nop"), }; *instruction.operation_mut() = Operation::Nop(Some(Box::new(instruction.operation().clone()))); Ok(()) } /// Creates an instruction for an operation and prepends it to the beginning /// of the block. pub fn prepend_operation(&mut self, operation: Operation) { let instruction = Instruction::new(self.next_index(), operation, None); self.instructions.insert(0, instruction); } } impl graph::Vertex for Block { fn index(&self) -> usize { self.index } fn dot_label(&self) -> String { format!("{}", self) } } impl fmt::Display for Block { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { writeln!(f, "[ Block 0x{:02x} ]", self.index())?; for instruction in self.instructions() { if instruction.operation().is_nop() { continue; } writeln!(f, "{}", instruction)?; } Ok(()) } }