use crate::type_info::TypeInfo; use std::fmt::{Debug, Display, Formatter}; use std::hash::Hash; use std::rc::Rc; pub struct IrVariable { descriptor: IrVariableDescriptor, type_info: TypeInfo, } impl IrVariable { pub fn new_vr(name: Rc, block_id: usize, type_info: TypeInfo) -> Self { Self { descriptor: IrVariableDescriptor::VirtualRegister(IrVrVariableDescriptor::new( name, block_id, )), type_info, } } pub fn new_stack(name: Rc, block_id: usize, type_info: TypeInfo) -> Self { Self { descriptor: IrVariableDescriptor::Stack(IrStackVariableDescriptor::new(name, block_id)), type_info, } } pub fn type_info(&self) -> &TypeInfo { &self.type_info } pub fn descriptor(&self) -> &IrVariableDescriptor { &self.descriptor } pub fn set_descriptor(&mut self, descriptor: IrVariableDescriptor) { self.descriptor = descriptor; } } impl Display for IrVariable { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.descriptor) } } pub enum IrVariableDescriptor { VirtualRegister(IrVrVariableDescriptor), Stack(IrStackVariableDescriptor), } impl Display for IrVariableDescriptor { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { IrVariableDescriptor::VirtualRegister(vr_variable) => { write!(f, "{}", vr_variable) } IrVariableDescriptor::Stack(stack_variable) => { write!(f, "{}", stack_variable) } } } } impl IrVariableDescriptor { pub fn name(&self) -> &str { match self { IrVariableDescriptor::VirtualRegister(vr_variable) => vr_variable.name(), IrVariableDescriptor::Stack(stack_variable) => stack_variable.name(), } } } #[derive(Clone, Hash, PartialEq, Eq)] pub struct IrVrVariableDescriptor { name: Rc, block_id: usize, assigned_register: Option, } impl IrVrVariableDescriptor { pub fn new(name: Rc, block_id: usize) -> Self { Self { name, block_id, assigned_register: None, } } pub fn name(&self) -> &str { &self.name } pub fn block_id(&self) -> usize { self.block_id } } impl Display for IrVrVariableDescriptor { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.name) } } impl Debug for IrVrVariableDescriptor { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.name) } } pub struct IrStackVariableDescriptor { name: Rc, block_id: usize, offset: Option, } impl IrStackVariableDescriptor { pub fn new(name: Rc, block_id: usize) -> Self { Self { name, block_id, offset: None, } } pub fn name(&self) -> &str { &self.name } } impl Display for IrStackVariableDescriptor { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{}_b{}", self.name, self.block_id) } }