xref: /wasmtime-44.0.1/pulley/src/encode.rs (revision 128decdd)
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 u128 {
63     const WIDTH: u8 = 16;
64 
65     fn encode<E>(&self, sink: &mut E)
66     where
67         E: Extend<u8>,
68     {
69         sink.extend(self.to_le_bytes());
70     }
71 }
72 
73 impl Encode for i8 {
74     const WIDTH: u8 = 1;
75 
76     fn encode<E>(&self, sink: &mut E)
77     where
78         E: Extend<u8>,
79     {
80         sink.extend(core::iter::once(*self as u8));
81     }
82 }
83 
84 impl Encode for i16 {
85     const WIDTH: u8 = 2;
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 i32 {
96     const WIDTH: u8 = 4;
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 i64 {
107     const WIDTH: u8 = 8;
108 
109     fn encode<E>(&self, sink: &mut E)
110     where
111         E: Extend<u8>,
112     {
113         sink.extend(self.to_le_bytes());
114     }
115 }
116 
117 impl Encode for i128 {
118     const WIDTH: u8 = 16;
119 
120     fn encode<E>(&self, sink: &mut E)
121     where
122         E: Extend<u8>,
123     {
124         sink.extend(self.to_le_bytes());
125     }
126 }
127 
128 impl Encode for XReg {
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 FReg {
140     const WIDTH: u8 = 1;
141 
142     fn encode<E>(&self, sink: &mut E)
143     where
144         E: Extend<u8>,
145     {
146         sink.extend(core::iter::once(self.to_u8()));
147     }
148 }
149 
150 impl Encode for VReg {
151     const WIDTH: u8 = 1;
152 
153     fn encode<E>(&self, sink: &mut E)
154     where
155         E: Extend<u8>,
156     {
157         sink.extend(core::iter::once(self.to_u8()));
158     }
159 }
160 
161 impl Encode for PcRelOffset {
162     const WIDTH: u8 = 4;
163 
164     fn encode<E>(&self, sink: &mut E)
165     where
166         E: Extend<u8>,
167     {
168         i32::from(*self).encode(sink);
169     }
170 }
171 
172 impl<D: Reg, S1: Reg, S2: Reg> Encode for BinaryOperands<D, S1, S2> {
173     const WIDTH: u8 = 2;
174 
175     fn encode<E>(&self, sink: &mut E)
176     where
177         E: Extend<u8>,
178     {
179         self.to_bits().encode(sink);
180     }
181 }
182 
183 impl<R: Reg + Encode> Encode for RegSet<R> {
184     const WIDTH: u8 = 4;
185 
186     fn encode<E>(&self, sink: &mut E)
187     where
188         E: Extend<u8>,
189     {
190         self.to_bitset().0.encode(sink);
191     }
192 }
193 
194 macro_rules! impl_encoders {
195     (
196         $(
197             $( #[$attr:meta] )*
198                 $snake_name:ident = $name:ident $( {
199                 $(
200                     $( #[$field_attr:meta] )*
201                     $field:ident : $field_ty:ty
202                 ),*
203             } )? ;
204         )*
205     ) => {
206         $(
207             $( #[$attr] )*
208             pub fn $snake_name<E>(into: &mut E $( $( , $field : impl Into<$field_ty> )* )? )
209             where
210                 E: Extend<u8>,
211             {
212                 into.extend(core::iter::once(Opcode::$name as u8));
213                 $(
214                     $(
215                         $field.into().encode(into);
216                     )*
217                 )?
218             }
219 
220             impl Encode for crate::op::$name {
221                 const WIDTH: u8 = 1 $($( + <$field_ty as Encode>::WIDTH)*)?;
222 
223                 fn encode<E>(&self, sink: &mut E)
224                 where
225                     E: Extend<u8>,
226                 {
227                     let Self { $(  $( $field ),* )? } = *self;
228                     $snake_name(sink $( $(, $field)* )?)
229                 }
230             }
231         )*
232     };
233 }
234 for_each_op!(impl_encoders);
235 
236 macro_rules! impl_extended_encoders {
237     (
238         $(
239             $( #[$attr:meta] )*
240                 $snake_name:ident = $name:ident $( {
241                     $(
242                         $( #[$field_attr:meta] )*
243                         $field:ident : $field_ty:ty
244                     ),*
245                 } )? ;
246         )*
247     ) => {
248         $(
249             $( #[$attr] )*
250             pub fn $snake_name<E>(into: &mut E $( $( , $field : impl Into<$field_ty> )* )? )
251             where
252                 E: Extend<u8>,
253             {
254                 into.extend(core::iter::once(Opcode::ExtendedOp as u8));
255                 into.extend((ExtendedOpcode::$name as u16).to_le_bytes());
256                 $(
257                     $(
258                         $field.into().encode(into);
259                     )*
260                 )?
261             }
262 
263             impl Encode for crate::op::$name {
264                 const WIDTH: u8 = 3 $($( + <$field_ty as Encode>::WIDTH)*)?;
265 
266                 fn encode<E>(&self, sink: &mut E)
267                 where
268                     E: Extend<u8>,
269                 {
270                     let Self { $(  $( $field ),* )? } = *self;
271                     $snake_name(sink $( $(, $field)* )?)
272                 }
273             }
274         )*
275     };
276 }
277 for_each_extended_op!(impl_extended_encoders);
278