xref: /wasmtime-44.0.1/pulley/src/encode.rs (revision 70a37939)
1 //! Encoding support for pulley bytecode.
2 
3 use crate::imms::*;
4 use crate::opcode::{ExtendedOpcode, Opcode};
5 use crate::regs::*;
6 
7 /// Helper trait to encode instructions into a "sink".
8 pub trait Encode {
9     /// The encoded width of this instruction.
10     const WIDTH: u8;
11 
12     /// Encodes this operand or instruction into the provided `sink`.
13     fn encode<E>(&self, sink: &mut E)
14     where
15         E: Extend<u8>;
16 }
17 
18 impl Encode for u8 {
19     const WIDTH: u8 = 1;
20 
21     fn encode<E>(&self, sink: &mut E)
22     where
23         E: Extend<u8>,
24     {
25         sink.extend(core::iter::once(*self));
26     }
27 }
28 
29 impl Encode for u16 {
30     const WIDTH: u8 = 2;
31 
32     fn encode<E>(&self, sink: &mut E)
33     where
34         E: Extend<u8>,
35     {
36         sink.extend(self.to_le_bytes());
37     }
38 }
39 
40 impl Encode for u32 {
41     const WIDTH: u8 = 4;
42 
43     fn encode<E>(&self, sink: &mut E)
44     where
45         E: Extend<u8>,
46     {
47         sink.extend(self.to_le_bytes());
48     }
49 }
50 
51 impl Encode for u64 {
52     const WIDTH: u8 = 8;
53 
54     fn encode<E>(&self, sink: &mut E)
55     where
56         E: Extend<u8>,
57     {
58         sink.extend(self.to_le_bytes());
59     }
60 }
61 
62 impl Encode for i8 {
63     const WIDTH: u8 = 1;
64 
65     fn encode<E>(&self, sink: &mut E)
66     where
67         E: Extend<u8>,
68     {
69         sink.extend(core::iter::once(*self as u8));
70     }
71 }
72 
73 impl Encode for i16 {
74     const WIDTH: u8 = 2;
75 
76     fn encode<E>(&self, sink: &mut E)
77     where
78         E: Extend<u8>,
79     {
80         sink.extend(self.to_le_bytes());
81     }
82 }
83 
84 impl Encode for i32 {
85     const WIDTH: u8 = 4;
86 
87     fn encode<E>(&self, sink: &mut E)
88     where
89         E: Extend<u8>,
90     {
91         sink.extend(self.to_le_bytes());
92     }
93 }
94 
95 impl Encode for i64 {
96     const WIDTH: u8 = 8;
97 
98     fn encode<E>(&self, sink: &mut E)
99     where
100         E: Extend<u8>,
101     {
102         sink.extend(self.to_le_bytes());
103     }
104 }
105 
106 impl Encode for XReg {
107     const WIDTH: u8 = 1;
108 
109     fn encode<E>(&self, sink: &mut E)
110     where
111         E: Extend<u8>,
112     {
113         sink.extend(core::iter::once(self.to_u8()));
114     }
115 }
116 
117 impl Encode for FReg {
118     const WIDTH: u8 = 1;
119 
120     fn encode<E>(&self, sink: &mut E)
121     where
122         E: Extend<u8>,
123     {
124         sink.extend(core::iter::once(self.to_u8()));
125     }
126 }
127 
128 impl Encode for VReg {
129     const WIDTH: u8 = 1;
130 
131     fn encode<E>(&self, sink: &mut E)
132     where
133         E: Extend<u8>,
134     {
135         sink.extend(core::iter::once(self.to_u8()));
136     }
137 }
138 
139 impl Encode for PcRelOffset {
140     const WIDTH: u8 = 4;
141 
142     fn encode<E>(&self, sink: &mut E)
143     where
144         E: Extend<u8>,
145     {
146         i32::from(*self).encode(sink);
147     }
148 }
149 
150 impl<R: Reg> Encode for BinaryOperands<R> {
151     const WIDTH: u8 = 2;
152 
153     fn encode<E>(&self, sink: &mut E)
154     where
155         E: Extend<u8>,
156     {
157         self.to_bits().encode(sink);
158     }
159 }
160 
161 impl<R: Reg + Encode> Encode for RegSet<R> {
162     const WIDTH: u8 = 4;
163 
164     fn encode<E>(&self, sink: &mut E)
165     where
166         E: Extend<u8>,
167     {
168         self.to_bitset().0.encode(sink);
169     }
170 }
171 
172 macro_rules! impl_encoders {
173     (
174         $(
175             $( #[$attr:meta] )*
176                 $snake_name:ident = $name:ident $( {
177                 $(
178                     $( #[$field_attr:meta] )*
179                     $field:ident : $field_ty:ty
180                 ),*
181             } )? ;
182         )*
183     ) => {
184         $(
185             $( #[$attr] )*
186             pub fn $snake_name<E>(into: &mut E $( $( , $field : impl Into<$field_ty> )* )? )
187             where
188                 E: Extend<u8>,
189             {
190                 into.extend(core::iter::once(Opcode::$name as u8));
191                 $(
192                     $(
193                         $field.into().encode(into);
194                     )*
195                 )?
196             }
197 
198             impl Encode for crate::op::$name {
199                 const WIDTH: u8 = 1 $($( + <$field_ty as Encode>::WIDTH)*)?;
200 
201                 fn encode<E>(&self, sink: &mut E)
202                 where
203                     E: Extend<u8>,
204                 {
205                     let Self { $(  $( $field ),* )? } = *self;
206                     $snake_name(sink $( $(, $field)* )?)
207                 }
208             }
209         )*
210     };
211 }
212 for_each_op!(impl_encoders);
213 
214 macro_rules! impl_extended_encoders {
215     (
216         $(
217             $( #[$attr:meta] )*
218                 $snake_name:ident = $name:ident $( {
219                     $(
220                         $( #[$field_attr:meta] )*
221                         $field:ident : $field_ty:ty
222                     ),*
223                 } )? ;
224         )*
225     ) => {
226         $(
227             $( #[$attr] )*
228             pub fn $snake_name<E>(into: &mut E $( $( , $field : impl Into<$field_ty> )* )? )
229             where
230                 E: Extend<u8>,
231             {
232                 into.extend(core::iter::once(Opcode::ExtendedOp as u8));
233                 into.extend((ExtendedOpcode::$name as u16).to_le_bytes());
234                 $(
235                     $(
236                         $field.into().encode(into);
237                     )*
238                 )?
239             }
240 
241             impl Encode for crate::op::$name {
242                 const WIDTH: u8 = 3 $($( + <$field_ty as Encode>::WIDTH)*)?;
243 
244                 fn encode<E>(&self, sink: &mut E)
245                 where
246                     E: Extend<u8>,
247                 {
248                     let Self { $(  $( $field ),* )? } = *self;
249                     $snake_name(sink $( $(, $field)* )?)
250                 }
251             }
252         )*
253     };
254 }
255 for_each_extended_op!(impl_extended_encoders);
256