//! Encoding support for pulley bytecode. use crate::imms::*; use crate::opcode::{ExtendedOpcode, Opcode}; use crate::regs::*; trait Encode { fn encode(&self, sink: &mut E) where E: Extend; } impl Encode for u8 { fn encode(&self, sink: &mut E) where E: Extend, { sink.extend(core::iter::once(*self)); } } impl Encode for u16 { fn encode(&self, sink: &mut E) where E: Extend, { sink.extend(self.to_le_bytes()); } } impl Encode for u32 { fn encode(&self, sink: &mut E) where E: Extend, { sink.extend(self.to_le_bytes()); } } impl Encode for u64 { fn encode(&self, sink: &mut E) where E: Extend, { sink.extend(self.to_le_bytes()); } } impl Encode for i8 { fn encode(&self, sink: &mut E) where E: Extend, { sink.extend(core::iter::once(*self as u8)); } } impl Encode for i16 { fn encode(&self, sink: &mut E) where E: Extend, { sink.extend(self.to_le_bytes()); } } impl Encode for i32 { fn encode(&self, sink: &mut E) where E: Extend, { sink.extend(self.to_le_bytes()); } } impl Encode for i64 { fn encode(&self, sink: &mut E) where E: Extend, { sink.extend(self.to_le_bytes()); } } impl Encode for XReg { fn encode(&self, sink: &mut E) where E: Extend, { sink.extend(core::iter::once(self.to_u8())); } } impl Encode for FReg { fn encode(&self, sink: &mut E) where E: Extend, { sink.extend(core::iter::once(self.to_u8())); } } impl Encode for VReg { fn encode(&self, sink: &mut E) where E: Extend, { sink.extend(core::iter::once(self.to_u8())); } } impl Encode for PcRelOffset { fn encode(&self, sink: &mut E) where E: Extend, { i32::from(*self).encode(sink); } } impl Encode for BinaryOperands { fn encode(&self, sink: &mut E) where E: Extend, { self.to_bits().encode(sink); } } impl Encode for RegSet { fn encode(&self, sink: &mut E) where E: Extend, { self.to_bitset().0.encode(sink); } } macro_rules! impl_encoders { ( $( $( #[$attr:meta] )* $snake_name:ident = $name:ident $( { $( $( #[$field_attr:meta] )* $field:ident : $field_ty:ty ),* } )? ; )* ) => { $( $( #[$attr] )* pub fn $snake_name(into: &mut E $( $( , $field : impl Into<$field_ty> )* )? ) where E: Extend, { into.extend(core::iter::once(Opcode::$name as u8)); $( $( $field.into().encode(into); )* )? } )* }; } for_each_op!(impl_encoders); macro_rules! impl_extended_encoders { ( $( $( #[$attr:meta] )* $snake_name:ident = $name:ident $( { $( $( #[$field_attr:meta] )* $field:ident : $field_ty:ty ),* } )? ; )* ) => { $( $( #[$attr] )* pub fn $snake_name(into: &mut E $( $( , $field : impl Into<$field_ty> )* )? ) where E: Extend, { into.extend(core::iter::once(Opcode::ExtendedOp as u8)); into.extend((ExtendedOpcode::$name as u16).to_le_bytes()); $( $( $field.into().encode(into); )* )? } )* }; } for_each_extended_op!(impl_extended_encoders);