Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/pulley/src/op.rs
1691 views
1
//! Pulley bytecode operations with their operands.
2
3
#[cfg(feature = "encode")]
4
use crate::encode::Encode;
5
use crate::imms::*;
6
use crate::regs::*;
7
8
macro_rules! define_op {
9
(
10
$(
11
$( #[$attr:meta] )*
12
$snake_name:ident = $name:ident $( { $( $field:ident : $field_ty:ty ),* } )? ;
13
)*
14
) => {
15
/// A complete, materialized operation/instruction.
16
///
17
/// This type is useful for debugging, writing tests, etc... but is not
18
/// actually ever used by the interpreter, encoder, or decoder, all of
19
/// which avoid materializing ops.
20
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
21
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
22
pub enum Op {
23
$(
24
$( #[$attr] )*
25
$name($name),
26
)*
27
/// An extended operation/instruction.
28
ExtendedOp(ExtendedOp),
29
}
30
31
$(
32
$( #[$attr] )*
33
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
34
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
35
pub struct $name { $(
36
$(
37
// TODO: add doc comments to all fields and update all
38
// the macros to match them.
39
#[expect(missing_docs, reason = "macro-generated code")]
40
pub $field : $field_ty,
41
)*
42
)? }
43
44
impl From<$name> for Op {
45
#[inline]
46
fn from(op: $name) -> Self {
47
Self::$name(op)
48
}
49
}
50
)*
51
};
52
}
53
for_each_op!(define_op);
54
55
impl From<ExtendedOp> for Op {
56
#[inline]
57
fn from(op: ExtendedOp) -> Self {
58
Op::ExtendedOp(op)
59
}
60
}
61
62
macro_rules! define_extended_op {
63
(
64
$(
65
$( #[$attr:meta] )*
66
$snake_name:ident = $name:ident $( { $( $field:ident : $field_ty:ty ),* } )? ;
67
)*
68
) => {
69
/// An extended operation/instruction.
70
///
71
/// These tend to be colder than `Op`s.
72
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
73
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
74
pub enum ExtendedOp {
75
$(
76
$( #[$attr] )*
77
$name($name),
78
)*
79
}
80
81
$(
82
$( #[$attr] )*
83
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
84
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
85
pub struct $name { $(
86
$(
87
// TODO: add doc comments to all fields and update all
88
// the macros to match them.
89
#[expect(missing_docs, reason = "macro-generated code")]
90
pub $field : $field_ty,
91
)*
92
)? }
93
94
#[doc(hidden)]
95
#[expect(non_camel_case_types, reason = "used in macros as an alternative to camel case")]
96
pub type $snake_name = $name;
97
98
impl From<$name> for Op {
99
#[inline]
100
fn from(op: $name) -> Self {
101
Self::ExtendedOp(ExtendedOp::$name(op))
102
}
103
}
104
105
impl From<$name> for ExtendedOp {
106
#[inline]
107
fn from(op: $name) -> Self {
108
Self::$name(op)
109
}
110
}
111
)*
112
};
113
}
114
for_each_extended_op!(define_extended_op);
115
116
macro_rules! define_op_encode {
117
(
118
$(
119
$( #[$attr:meta] )*
120
$snake_name:ident = $name:ident $( { $( $field:ident : $field_ty:ty ),* } )? ;
121
)*
122
) => {
123
impl Op {
124
/// Encode this op into the given sink.
125
#[cfg(feature = "encode")]
126
pub fn encode<E>(&self, into: &mut E)
127
where
128
E: Extend<u8>,
129
{
130
match self {
131
$(
132
Self::$name(op) => op.encode(into),
133
)*
134
Self::ExtendedOp(op) => op.encode(into),
135
}
136
}
137
138
/// Returns the encoded size of this op.
139
#[cfg(feature = "encode")]
140
pub fn width(&self) -> u8 {
141
match self {
142
$(
143
Self::$name(_) => <$name as Encode>::WIDTH,
144
)*
145
Self::ExtendedOp(op) => op.width(),
146
}
147
}
148
}
149
150
$(
151
impl $name {
152
/// Encode this
153
#[doc = concat!("`", stringify!($name), "`")]
154
/// op into the given sink.
155
#[cfg(feature = "encode")]
156
pub fn encode<E>(&self, into: &mut E)
157
where
158
E: Extend<u8>,
159
{
160
crate::encode::$snake_name(into $( $( , self.$field )* )?);
161
}
162
}
163
)*
164
};
165
}
166
for_each_op!(define_op_encode);
167
168
macro_rules! define_extended_op_encode {
169
(
170
$(
171
$( #[$attr:meta] )*
172
$snake_name:ident = $name:ident $( { $( $field:ident : $field_ty:ty ),* } )? ;
173
)*
174
) => {
175
impl ExtendedOp {
176
/// Encode this extended op into the given sink.
177
#[cfg(feature = "encode")]
178
pub fn encode<E>(&self, into: &mut E)
179
where
180
E: Extend<u8>,
181
{
182
match self {
183
$(
184
Self::$name(op) => op.encode(into),
185
)*
186
}
187
}
188
189
/// Returns the encoded size of this op.
190
#[cfg(feature = "encode")]
191
pub fn width(&self) -> u8 {
192
match self {
193
$(
194
Self::$name(_) => <$name as Encode>::WIDTH,
195
)*
196
}
197
}
198
}
199
200
$(
201
impl $name {
202
/// Encode this
203
#[doc = concat!("`", stringify!($name), "`")]
204
/// op into the given sink.
205
#[cfg(feature = "encode")]
206
pub fn encode<E>(&self, into: &mut E)
207
where
208
E: Extend<u8>,
209
{
210
crate::encode::$snake_name(into $( $( , self.$field )* )?);
211
}
212
}
213
)*
214
};
215
}
216
for_each_extended_op!(define_extended_op_encode);
217
218
/// A visitor that materializes whole `Op`s as it decodes the bytecode stream.
219
#[cfg(feature = "decode")]
220
#[derive(Default)]
221
pub struct MaterializeOpsVisitor<B> {
222
bytecode: B,
223
}
224
225
#[cfg(feature = "decode")]
226
impl<B> MaterializeOpsVisitor<B> {
227
/// Create a new op-materializing visitor for the given bytecode.
228
pub fn new(bytecode: B) -> Self {
229
Self { bytecode }
230
}
231
}
232
233
macro_rules! define_materialize_op_visitor {
234
(
235
$(
236
$( #[$attr:meta] )*
237
$snake_name:ident = $name:ident $( { $( $field:ident : $field_ty:ty ),* } )? ;
238
)*
239
) => {
240
#[cfg(feature = "decode")]
241
impl<B: crate::decode::BytecodeStream> crate::decode::OpVisitor for MaterializeOpsVisitor<B> {
242
type BytecodeStream = B;
243
244
fn bytecode(&mut self) -> &mut Self::BytecodeStream {
245
&mut self.bytecode
246
}
247
248
type Return = crate::op::Op;
249
250
$(
251
$( #[$attr] )*
252
fn $snake_name(&mut self $( $( , $field : $field_ty )* )? ) -> Self::Return {
253
crate::op::Op::$name(crate::op::$name { $( $(
254
$field,
255
)* )? })
256
}
257
)*
258
}
259
};
260
}
261
for_each_op!(define_materialize_op_visitor);
262
263
macro_rules! define_materialize_extended_op_visitor {
264
(
265
$(
266
$( #[$attr:meta] )*
267
$snake_name:ident = $name:ident $( { $( $field:ident : $field_ty:ty ),* } )? ;
268
)*
269
) => {
270
#[cfg(feature = "decode")]
271
impl<B: crate::decode::BytecodeStream> crate::decode::ExtendedOpVisitor for MaterializeOpsVisitor<B> {
272
$(
273
$( #[$attr] )*
274
fn $snake_name(&mut self $( $( , $field : $field_ty )* )? ) -> Self::Return {
275
crate::op::ExtendedOp::$name(crate::op::$name { $( $(
276
$field,
277
)* )? }).into()
278
}
279
)*
280
}
281
};
282
}
283
for_each_extended_op!(define_materialize_extended_op_visitor);
284
285