1 //! Program points. 2 3 use crate::ir::{Block, Inst}; 4 use core::fmt; 5 6 /// A `ProgramPoint` represents a position in a function where the live range of an SSA value can 7 /// begin or end. It can be either: 8 /// 9 /// 1. An instruction or 10 /// 2. A block header. 11 /// 12 /// This corresponds more or less to the lines in the textual form of Cranelift IR. 13 #[derive(PartialEq, Eq, Clone, Copy)] 14 pub enum ProgramPoint { 15 /// An instruction in the function. 16 Inst(Inst), 17 /// A block header. 18 Block(Block), 19 } 20 21 impl ProgramPoint { 22 /// Get the instruction we know is inside. unwrap_inst(self) -> Inst23 pub fn unwrap_inst(self) -> Inst { 24 match self { 25 Self::Inst(x) => x, 26 Self::Block(x) => panic!("expected inst: {x}"), 27 } 28 } 29 } 30 31 impl From<Inst> for ProgramPoint { from(inst: Inst) -> Self32 fn from(inst: Inst) -> Self { 33 Self::Inst(inst) 34 } 35 } 36 37 impl From<Block> for ProgramPoint { from(block: Block) -> Self38 fn from(block: Block) -> Self { 39 Self::Block(block) 40 } 41 } 42 43 impl fmt::Display for ProgramPoint { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result44 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 45 match *self { 46 Self::Inst(x) => write!(f, "{x}"), 47 Self::Block(x) => write!(f, "{x}"), 48 } 49 } 50 } 51 52 impl fmt::Debug for ProgramPoint { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result53 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 54 write!(f, "ProgramPoint({self})") 55 } 56 } 57 58 #[cfg(test)] 59 mod tests { 60 use super::*; 61 use crate::entity::EntityRef; 62 use alloc::string::ToString; 63 64 #[test] convert()65 fn convert() { 66 let i5 = Inst::new(5); 67 let b3 = Block::new(3); 68 69 let pp1: ProgramPoint = i5.into(); 70 let pp2: ProgramPoint = b3.into(); 71 72 assert_eq!(pp1.to_string(), "inst5"); 73 assert_eq!(pp2.to_string(), "block3"); 74 } 75 } 76