use core::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Type {
I1,
I32,
I64,
I128,
F32,
F64,
V128,
}
impl Type {
#[inline]
#[must_use]
pub const fn bits(self) -> u32 {
match self {
Type::I1 => 1,
Type::I32 | Type::F32 => 32,
Type::I64 | Type::F64 => 64,
Type::I128 | Type::V128 => 128,
}
}
#[inline]
#[must_use]
pub const fn is_int(self) -> bool {
matches!(self, Type::I1 | Type::I32 | Type::I64 | Type::I128)
}
#[inline]
#[must_use]
pub const fn is_float(self) -> bool {
matches!(self, Type::F32 | Type::F64)
}
}
impl fmt::Display for Type {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Type::I1 => "i1",
Type::I32 => "i32",
Type::I64 => "i64",
Type::I128 => "i128",
Type::F32 => "f32",
Type::F64 => "f64",
Type::V128 => "v128",
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct Temp(pub u32);
impl Temp {
#[inline]
#[must_use]
pub const fn index(self) -> usize {
self.0 as usize
}
}
impl fmt::Display for Temp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "t{}", self.0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Const {
Int(u128),
F32Bits(u32),
F64Bits(u64),
}
impl Const {
#[inline]
#[must_use]
pub const fn bits(self) -> u128 {
match self {
Const::Int(v) => v,
Const::F32Bits(v) => v as u128,
Const::F64Bits(v) => v as u128,
}
}
}
impl fmt::Display for Const {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Const::Int(v) => write!(f, "{v:#x}"),
Const::F32Bits(v) => write!(f, "f32:{v:#010x}"),
Const::F64Bits(v) => write!(f, "f64:{v:#018x}"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use alloc::format;
#[test]
fn every_type_reports_its_width() {
assert_eq!(Type::I1.bits(), 1);
assert_eq!(Type::I32.bits(), 32);
assert_eq!(Type::V128.bits(), 128);
assert!(Type::I1.is_int());
assert!(!Type::I1.is_float());
assert!(Type::F64.is_float());
assert!(!Type::V128.is_int() && !Type::V128.is_float());
}
#[test]
fn a_float_immediate_keeps_its_bits() {
let snan = Const::F64Bits(0x7ff0_0000_0000_0001);
assert_eq!(snan.bits(), 0x7ff0_0000_0000_0001);
assert_eq!(format!("{snan}"), "f64:0x7ff0000000000001");
}
#[test]
fn temps_display_as_they_index() {
assert_eq!(format!("{}", Temp(7)), "t7");
assert_eq!(Temp(7).index(), 7);
}
}