xref: /wasmtime-44.0.1/pulley/src/encode.rs (revision dd3aac60)
1 //! Encoding support for pulley bytecode.
2 
3 use crate::imms::*;
4 use crate::opcode::{ExtendedOpcode, Opcode};
5 use crate::regs::*;
6 
7 trait Encode {
8     fn encode<E>(&self, sink: &mut E)
9     where
10         E: Extend<u8>;
11 }
12 
13 impl Encode for u8 {
14     fn encode<E>(&self, sink: &mut E)
15     where
16         E: Extend<u8>,
17     {
18         sink.extend(core::iter::once(*self));
19     }
20 }
21 
22 impl Encode for u16 {
23     fn encode<E>(&self, sink: &mut E)
24     where
25         E: Extend<u8>,
26     {
27         sink.extend(self.to_le_bytes());
28     }
29 }
30 
31 impl Encode for u32 {
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 u64 {
41     fn encode<E>(&self, sink: &mut E)
42     where
43         E: Extend<u8>,
44     {
45         sink.extend(self.to_le_bytes());
46     }
47 }
48 
49 impl Encode for i8 {
50     fn encode<E>(&self, sink: &mut E)
51     where
52         E: Extend<u8>,
53     {
54         sink.extend(core::iter::once(*self as u8));
55     }
56 }
57 
58 impl Encode for i16 {
59     fn encode<E>(&self, sink: &mut E)
60     where
61         E: Extend<u8>,
62     {
63         sink.extend(self.to_le_bytes());
64     }
65 }
66 
67 impl Encode for i32 {
68     fn encode<E>(&self, sink: &mut E)
69     where
70         E: Extend<u8>,
71     {
72         sink.extend(self.to_le_bytes());
73     }
74 }
75 
76 impl Encode for i64 {
77     fn encode<E>(&self, sink: &mut E)
78     where
79         E: Extend<u8>,
80     {
81         sink.extend(self.to_le_bytes());
82     }
83 }
84 
85 impl Encode for XReg {
86     fn encode<E>(&self, sink: &mut E)
87     where
88         E: Extend<u8>,
89     {
90         sink.extend(core::iter::once(u8::try_from(self.index()).unwrap()));
91     }
92 }
93 
94 impl Encode for FReg {
95     fn encode<E>(&self, sink: &mut E)
96     where
97         E: Extend<u8>,
98     {
99         sink.extend(core::iter::once(u8::try_from(self.index()).unwrap()));
100     }
101 }
102 
103 impl Encode for VReg {
104     fn encode<E>(&self, sink: &mut E)
105     where
106         E: Extend<u8>,
107     {
108         sink.extend(core::iter::once(u8::try_from(self.index()).unwrap()));
109     }
110 }
111 
112 impl Encode for PcRelOffset {
113     fn encode<E>(&self, sink: &mut E)
114     where
115         E: Extend<u8>,
116     {
117         i32::from(*self).encode(sink);
118     }
119 }
120 
121 macro_rules! impl_encoders {
122     (
123         $(
124             $( #[$attr:meta] )*
125                 $snake_name:ident = $name:ident $( {
126                 $(
127                     $( #[$field_attr:meta] )*
128                     $field:ident : $field_ty:ty
129                 ),*
130             } )? ;
131         )*
132     ) => {
133         $(
134             $( #[$attr] )*
135             pub fn $snake_name<E>(into: &mut E $( $( , $field : impl Into<$field_ty> )* )? )
136             where
137                 E: Extend<u8>,
138             {
139                 into.extend(core::iter::once(Opcode::$name as u8));
140                 $(
141                     $(
142                         $field.into().encode(into);
143                     )*
144                 )?
145             }
146         )*
147     };
148 }
149 for_each_op!(impl_encoders);
150 
151 macro_rules! impl_extended_encoders {
152     (
153         $(
154             $( #[$attr:meta] )*
155                 $snake_name:ident = $name:ident $( {
156                     $(
157                         $( #[$field_attr:meta] )*
158                         $field:ident : $field_ty:ty
159                     ),*
160                 } )? ;
161         )*
162     ) => {
163         $(
164             $( #[$attr] )*
165             pub fn $snake_name<E>(into: &mut E $( $( , $field : impl Into<$field_ty> )* )? )
166             where
167                 E: Extend<u8>,
168             {
169                 into.extend(core::iter::once(Opcode::ExtendedOp as u8));
170                 into.extend((ExtendedOpcode::$name as u16).to_le_bytes());
171                 $(
172                     $(
173                         $field.into().encode(into);
174                     )*
175                 )?
176             }
177         )*
178     };
179 }
180 for_each_extended_op!(impl_extended_encoders);
181