use super::{LocalIdx, StackOperand, StackPos};
use crate::{
ValType,
core::{RawVal, TypedRawVal},
engine::translator::utils::required_cells_for_ty,
ir::{BoundedSlotSpan, SlotSpan},
};
#[cfg(doc)]
use super::Stack;
#[derive(Debug, Copy, Clone)]
pub enum Operand {
Local(LocalOperand),
Temp(TempOperand),
Immediate(ImmediateOperand),
}
impl Operand {
pub(super) fn new(stack_pos: StackPos, operand: StackOperand) -> Self {
match operand {
StackOperand::Local {
local_index,
ty,
temp_slots,
..
} => Self::local(temp_slots, local_index, ty),
StackOperand::Temp { ty, temp_slots, .. } => Self::temp(stack_pos, temp_slots, ty),
StackOperand::Immediate {
ty,
temp_slots,
val,
..
} => Self::immediate(temp_slots, ty, val),
}
}
pub fn is_same(&self, other: &Self) -> bool {
match (self, other) {
(Self::Local(lhs), Self::Local(rhs)) => lhs.local_index() == rhs.local_index(),
(Self::Temp(lhs), Self::Temp(rhs)) => lhs.stack_pos() == rhs.stack_pos(),
(Self::Immediate(lhs), Self::Immediate(rhs)) => lhs.val() == rhs.val(),
_ => false,
}
}
pub(super) fn local(temp_slots: SlotSpan, local_index: LocalIdx, ty: ValType) -> Self {
Self::Local(LocalOperand {
temp_slots,
ty,
local_index,
})
}
pub(super) fn temp(stack_pos: StackPos, temp_slots: SlotSpan, ty: ValType) -> Self {
Self::Temp(TempOperand {
temp_slots,
ty,
stack_pos,
})
}
pub(super) fn immediate(temp_slots: SlotSpan, ty: ValType, val: RawVal) -> Self {
Self::Immediate(ImmediateOperand {
temp_slots,
ty,
val,
})
}
pub fn is_temp(&self) -> bool {
matches!(self, Self::Temp(_))
}
pub fn temp_slots(&self) -> BoundedSlotSpan {
match self {
Self::Local(operand) => operand.temp_slots(),
Self::Temp(operand) => operand.temp_slots(),
Self::Immediate(operand) => operand.temp_slots(),
}
}
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 {
temp_slots: SlotSpan,
ty: ValType,
local_index: LocalIdx,
}
impl From<LocalOperand> for Operand {
fn from(operand: LocalOperand) -> Self {
Self::Local(operand)
}
}
impl LocalOperand {
pub(super) fn new(temp_slots: SlotSpan, ty: ValType, local_index: LocalIdx) -> Self {
Self {
temp_slots,
ty,
local_index,
}
}
pub fn temp_slots(&self) -> BoundedSlotSpan {
let len = required_cells_for_ty(self.ty());
BoundedSlotSpan::new(self.temp_slots, len)
}
pub fn local_index(&self) -> LocalIdx {
self.local_index
}
pub fn ty(&self) -> ValType {
self.ty
}
}
#[derive(Debug, Copy, Clone)]
pub struct TempOperand {
temp_slots: SlotSpan,
ty: ValType,
stack_pos: StackPos,
}
impl From<TempOperand> for Operand {
fn from(operand: TempOperand) -> Self {
Self::Temp(operand)
}
}
impl TempOperand {
pub(super) fn new(temp_slots: SlotSpan, ty: ValType, stack_pos: StackPos) -> Self {
Self {
temp_slots,
ty,
stack_pos,
}
}
fn stack_pos(&self) -> StackPos {
self.stack_pos
}
pub fn temp_slots(&self) -> BoundedSlotSpan {
let len = required_cells_for_ty(self.ty());
BoundedSlotSpan::new(self.temp_slots, len)
}
pub fn ty(&self) -> ValType {
self.ty
}
}
#[derive(Debug, Copy, Clone)]
pub struct ImmediateOperand {
temp_slots: SlotSpan,
ty: ValType,
val: RawVal,
}
impl From<ImmediateOperand> for Operand {
fn from(operand: ImmediateOperand) -> Self {
Self::Immediate(operand)
}
}
impl ImmediateOperand {
pub(super) fn new(temp_slots: SlotSpan, ty: ValType, val: RawVal) -> Self {
Self {
temp_slots,
ty,
val,
}
}
pub fn temp_slots(&self) -> BoundedSlotSpan {
let len = required_cells_for_ty(self.ty());
BoundedSlotSpan::new(self.temp_slots, len)
}
pub fn val(&self) -> TypedRawVal {
TypedRawVal::new(self.ty, self.val)
}
pub fn ty(&self) -> ValType {
self.ty
}
}
impl AsRef<Operand> for Operand {
fn as_ref(&self) -> &Operand {
self
}
}