//! Program points.
use crate::ir::{Block, Inst};
use core::fmt;
/// A `ProgramPoint` represents a position in a function where the live range of an SSA value can
/// begin or end. It can be either:
///
/// 1. An instruction or
/// 2. A block header.
///
/// This corresponds more or less to the lines in the textual form of Cranelift IR.
#[derive(PartialEq, Eq, Clone, Copy)]
pub enum ProgramPoint {
/// An instruction in the function.
Inst(Inst),
/// A block header.
Block(Block),
}
impl ProgramPoint {
/// Get the instruction we know is inside.
pub fn unwrap_inst(self) -> Inst {
match self {
Self::Inst(x) => x,
Self::Block(x) => panic!("expected inst: {x}"),
}
}
}
impl From<Inst> for ProgramPoint {
fn from(inst: Inst) -> Self {
Self::Inst(inst)
}
}
impl From<Block> for ProgramPoint {
fn from(block: Block) -> Self {
Self::Block(block)
}
}
impl fmt::Display for ProgramPoint {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Self::Inst(x) => write!(f, "{x}"),
Self::Block(x) => write!(f, "{x}"),
}
}
}
impl fmt::Debug for ProgramPoint {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ProgramPoint({self})")
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::entity::EntityRef;
use alloc::string::ToString;
#[test]
fn convert() {
let i5 = Inst::new(5);
let b3 = Block::new(3);
let pp1: ProgramPoint = i5.into();
let pp2: ProgramPoint = b3.into();
assert_eq!(pp1.to_string(), "inst5");
assert_eq!(pp2.to_string(), "block3");
}
}