use super::{LocalIdx, OperandIdx, StackOperand};
use crate::{core::TypedVal, engine::translator::utils::Instr, ValType};
#[cfg(doc)]
use super::Stack;
#[derive(Debug, Copy, Clone)]
pub enum Operand {
Local(LocalOperand),
Temp(TempOperand),
Immediate(ImmediateOperand),
}
impl Operand {
pub(super) fn new(index: OperandIdx, operand: StackOperand) -> Self {
match operand {
StackOperand::Local {
local_index, ty, ..
} => Self::local(index, local_index, ty),
StackOperand::Temp { ty, instr } => Self::temp(index, ty, instr),
StackOperand::Immediate { val } => Self::immediate(index, val),
}
}
pub fn is_same(&self, other: &Self) -> bool {
match (self, other) {
(Operand::Local(lhs), Operand::Local(rhs)) => lhs.local_index() == rhs.local_index(),
(Operand::Temp(lhs), Operand::Temp(rhs)) => lhs.operand_index() == rhs.operand_index(),
(Operand::Immediate(lhs), Operand::Immediate(rhs)) => lhs.val() == rhs.val(),
_ => false,
}
}
pub(super) fn local(operand_index: OperandIdx, local_index: LocalIdx, ty: ValType) -> Self {
Self::Local(LocalOperand {
operand_index,
local_index,
ty,
})
}
pub(super) fn temp(operand_index: OperandIdx, ty: ValType, instr: Option<Instr>) -> Self {
Self::Temp(TempOperand {
operand_index,
ty,
instr,
})
}
pub(super) fn immediate(operand_index: OperandIdx, val: TypedVal) -> Self {
Self::Immediate(ImmediateOperand { operand_index, val })
}
pub fn is_temp(&self) -> bool {
matches!(self, Self::Temp(_))
}
pub fn index(&self) -> OperandIdx {
match self {
Operand::Local(operand) => operand.operand_index(),
Operand::Temp(operand) => operand.operand_index(),
Operand::Immediate(operand) => operand.operand_index(),
}
}
pub fn ty(&self) -> ValType {
match self {
Self::Local(operand) => operand.ty(),
Self::Temp(operand) => operand.ty(),
Self::Immediate(operand) => operand.ty(),
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct LocalOperand {
operand_index: OperandIdx,
local_index: LocalIdx,
ty: ValType,
}
impl From<LocalOperand> for Operand {
fn from(operand: LocalOperand) -> Self {
Self::Local(operand)
}
}
impl LocalOperand {
pub fn operand_index(&self) -> OperandIdx {
self.operand_index
}
pub fn local_index(&self) -> LocalIdx {
self.local_index
}
pub fn ty(&self) -> ValType {
self.ty
}
}
#[derive(Debug, Copy, Clone)]
pub struct TempOperand {
operand_index: OperandIdx,
ty: ValType,
instr: Option<Instr>,
}
impl From<TempOperand> for Operand {
fn from(operand: TempOperand) -> Self {
Self::Temp(operand)
}
}
impl TempOperand {
pub fn operand_index(&self) -> OperandIdx {
self.operand_index
}
pub fn ty(&self) -> ValType {
self.ty
}
pub fn instr(&self) -> Option<Instr> {
self.instr
}
}
#[derive(Debug, Copy, Clone)]
pub struct ImmediateOperand {
operand_index: OperandIdx,
val: TypedVal,
}
impl From<ImmediateOperand> for Operand {
fn from(operand: ImmediateOperand) -> Self {
Self::Immediate(operand)
}
}
impl ImmediateOperand {
pub fn operand_index(&self) -> OperandIdx {
self.operand_index
}
pub fn val(&self) -> TypedVal {
self.val
}
pub fn ty(&self) -> ValType {
self.val.ty()
}
}
impl AsRef<Operand> for Operand {
fn as_ref(&self) -> &Operand {
self
}
}