use std::fmt::Debug;
use serde::{Deserialize, Serialize};
use crate::arch::{Arch, Register};
use crate::value::ValueType;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub enum LocationKind {
Reg,
Memory,
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub enum Location<A: Arch> {
Reg(A::Reg),
Memory(usize),
}
impl<A: Arch> Location<A> {
pub fn kind(&self) -> LocationKind {
match self {
Location::Reg(_) => LocationKind::Reg,
Location::Memory(_) => LocationKind::Memory,
}
}
pub fn matches_value_type_with(&self, other: &Location<A>) -> bool {
match (self, other) {
(Location::Reg(a), Location::Reg(b)) => a.reg_type() == b.reg_type(),
(Location::Reg(r), Location::Memory(_)) => matches!(r.reg_type(), ValueType::Bytes(_)),
(Location::Memory(_), Location::Reg(r)) => matches!(r.reg_type(), ValueType::Bytes(_)),
(Location::Memory(_), Location::Memory(_)) => true,
}
}
pub fn is_flags(&self) -> bool {
if let Location::Reg(reg) = self {
reg.is_flags()
} else {
false
}
}
}
impl<A: Arch> Debug for Location<A> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Location::Reg(reg) => write!(f, "Reg[{reg}]")?,
Location::Memory(index) => write!(f, "Memory[#{index}]")?,
}
Ok(())
}
}