diff --git a/src/libcretonne/isa/encoding.rs b/src/libcretonne/isa/encoding.rs index 1b26e2bab9..0bb1f6cc62 100644 --- a/src/libcretonne/isa/encoding.rs +++ b/src/libcretonne/isa/encoding.rs @@ -1,5 +1,7 @@ //! The `Encoding` struct. +use std::fmt; + /// Bits needed to encode an instruction as binary machine code. /// /// The encoding consists of two parts, both specific to the target ISA: An encoding *recipe*, and @@ -30,4 +32,47 @@ impl Encoding { pub fn bits(self) -> u16 { self.bits } + + /// Is this a legal encoding, or the default placeholder? + pub fn is_legal(self) -> bool { + self != Self::default() + } +} + +/// The default encoding is the illegal one. +impl Default for Encoding { + fn default() -> Self { + Self::new(0xffff, 0xffff) + } +} + +/// ISA-independent display of an encoding. +impl fmt::Display for Encoding { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.is_legal() { + write!(f, "#{}/{:02x}", self.recipe, self.bits) + } else { + write!(f, "-") + } + } +} + +/// Temporary object that holds enough context to properly display an encoding. +/// This is meant to be created by `TargetIsa::display_enc()`. +pub struct DisplayEncoding { + pub encoding: Encoding, + pub recipe_names: &'static [&'static str], +} + +impl fmt::Display for DisplayEncoding { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.encoding.is_legal() { + write!(f, + "{}/{:02x}", + self.recipe_names[self.encoding.recipe()], + self.encoding.bits) + } else { + write!(f, "-") + } + } } diff --git a/src/libcretonne/isa/mod.rs b/src/libcretonne/isa/mod.rs index 445893ee15..1d788ffff1 100644 --- a/src/libcretonne/isa/mod.rs +++ b/src/libcretonne/isa/mod.rs @@ -101,4 +101,12 @@ pub trait TargetIsa { /// /// This is just used for printing and parsing encodings in the textual IL format. fn recipe_names(&self) -> &'static [&'static str]; + + /// Create an object that can display an ISA-dependent encoding properly. + fn display_enc(&self, enc: Encoding) -> encoding::DisplayEncoding { + encoding::DisplayEncoding { + encoding: enc, + recipe_names: self.recipe_names(), + } + } } diff --git a/src/libcretonne/isa/riscv/mod.rs b/src/libcretonne/isa/riscv/mod.rs index 0f8ec7c71b..b1ee92a4a9 100644 --- a/src/libcretonne/isa/riscv/mod.rs +++ b/src/libcretonne/isa/riscv/mod.rs @@ -65,7 +65,7 @@ mod tests { use ir::{types, immediates}; fn encstr(isa: &isa::TargetIsa, enc: isa::Encoding) -> String { - format!("{}/{:02x}", isa.recipe_names()[enc.recipe()], enc.bits()) + isa.display_enc(enc).to_string() } #[test]