use std::fmt::{self, Display, Formatter}; use std::convert::TryFrom; use std::sync::atomic::AtomicU32; use std::borrow::Cow; pub type DebugMsg = Cow<'static, str>; /// Immediate value #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub struct Value(pub i64); impl From for Value { fn from(n: i64) -> Self { Self(n) } } impl Display for Value { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { if f.alternate() { write!(f, "{:#010x}", self.0) } else { write!(f, "{}", self.0) } } } impl Value { pub fn as_u64(self) -> u64 { u64::from_ne_bytes(self.0.to_ne_bytes()) } pub fn as_u32(self) -> Option { u32::try_from(self.as_u64()).ok() } pub fn as_i32(self) -> Option { i32::try_from(self.0).ok() } } /// Immediate address #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub struct Addr(pub u64); impl Display for Addr { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "@{:#010x}", self.0) } } impl From for Addr { fn from(n: u64) -> Self { Self(n) } } /// Label name #[derive(Debug, Clone, Eq, PartialEq)] pub enum Label { Named(String), Numbered(u32), } impl Label { /// Generate a unique numbered label from a counter pub fn unique(counter : &AtomicU32) -> Self { Label::Numbered(counter.fetch_add(1, std::sync::atomic::Ordering::Relaxed)) } } impl Display for Label { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { Label::Named(name) => write!(f, ":{}", name), Label::Numbered(num) => write!(f, ":#{}", num), } } } impl From<&str> for Label { fn from(n: &str) -> Self { Self::Named(n.to_string()) } } impl From for Label { fn from(n: String) -> Self { Self::Named(n) } } /// Routine name #[derive(Debug, Clone, Eq, PartialEq)] pub struct RoutineName(pub String); impl Display for RoutineName { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "{}", self.0) } } impl From<&str> for RoutineName { fn from(n: &str) -> Self { Self(n.to_string()) } } impl From for RoutineName { fn from(n: String) -> Self { Self(n) } }