Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/pulley/src/encode.rs
1692 views
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<D: Reg, S1: Reg> Encode for BinaryOperands<D, S1, U6> {
184
const WIDTH: u8 = 2;
185
186
fn encode<E>(&self, sink: &mut E)
187
where
188
E: Extend<u8>,
189
{
190
self.to_bits().encode(sink);
191
}
192
}
193
194
impl<R: Reg + Encode> Encode for UpperRegSet<R> {
195
const WIDTH: u8 = 2;
196
197
fn encode<E>(&self, sink: &mut E)
198
where
199
E: Extend<u8>,
200
{
201
self.to_bitset().0.encode(sink);
202
}
203
}
204
205
impl Encode for AddrO32 {
206
const WIDTH: u8 = 5;
207
208
fn encode<E>(&self, sink: &mut E)
209
where
210
E: Extend<u8>,
211
{
212
self.addr.encode(sink);
213
self.offset.encode(sink);
214
}
215
}
216
217
impl Encode for AddrZ {
218
const WIDTH: u8 = 5;
219
220
fn encode<E>(&self, sink: &mut E)
221
where
222
E: Extend<u8>,
223
{
224
self.addr.encode(sink);
225
self.offset.encode(sink);
226
}
227
}
228
229
impl Encode for AddrG32 {
230
const WIDTH: u8 = 4;
231
232
fn encode<E>(&self, sink: &mut E)
233
where
234
E: Extend<u8>,
235
{
236
self.to_bits().encode(sink);
237
}
238
}
239
240
impl Encode for AddrG32Bne {
241
const WIDTH: u8 = 4;
242
243
fn encode<E>(&self, sink: &mut E)
244
where
245
E: Extend<u8>,
246
{
247
self.to_bits().encode(sink);
248
}
249
}
250
251
macro_rules! impl_encoders {
252
(
253
$(
254
$( #[$attr:meta] )*
255
$snake_name:ident = $name:ident $( {
256
$(
257
$( #[$field_attr:meta] )*
258
$field:ident : $field_ty:ty
259
),*
260
} )? ;
261
)*
262
) => {
263
$(
264
$( #[$attr] )*
265
pub fn $snake_name<E>(into: &mut E $( $( , $field : impl Into<$field_ty> )* )? )
266
where
267
E: Extend<u8>,
268
{
269
into.extend(core::iter::once(Opcode::$name as u8));
270
$(
271
$(
272
$field.into().encode(into);
273
)*
274
)?
275
}
276
277
impl Encode for crate::op::$name {
278
const WIDTH: u8 = 1 $($( + <$field_ty as Encode>::WIDTH)*)?;
279
280
fn encode<E>(&self, sink: &mut E)
281
where
282
E: Extend<u8>,
283
{
284
let Self { $( $( $field ),* )? } = *self;
285
$snake_name(sink $( $(, $field)* )?)
286
}
287
}
288
)*
289
};
290
}
291
for_each_op!(impl_encoders);
292
293
macro_rules! impl_extended_encoders {
294
(
295
$(
296
$( #[$attr:meta] )*
297
$snake_name:ident = $name:ident $( {
298
$(
299
$( #[$field_attr:meta] )*
300
$field:ident : $field_ty:ty
301
),*
302
} )? ;
303
)*
304
) => {
305
$(
306
$( #[$attr] )*
307
pub fn $snake_name<E>(into: &mut E $( $( , $field : impl Into<$field_ty> )* )? )
308
where
309
E: Extend<u8>,
310
{
311
into.extend(core::iter::once(Opcode::ExtendedOp as u8));
312
into.extend((ExtendedOpcode::$name as u16).to_le_bytes());
313
$(
314
$(
315
$field.into().encode(into);
316
)*
317
)?
318
}
319
320
impl Encode for crate::op::$name {
321
const WIDTH: u8 = 3 $($( + <$field_ty as Encode>::WIDTH)*)?;
322
323
fn encode<E>(&self, sink: &mut E)
324
where
325
E: Extend<u8>,
326
{
327
let Self { $( $( $field ),* )? } = *self;
328
$snake_name(sink $( $(, $field)* )?)
329
}
330
}
331
)*
332
};
333
}
334
for_each_extended_op!(impl_extended_encoders);
335
336