1use super::{FuncAddr, GlobalAddr, LocalAddr, TableAddr, TypeAddr, ValueCounts, WasmType};
2use crate::{ConstIdx, DataAddr, ElemAddr, ExternAddr, MemAddr};
3
4#[derive(Copy, Clone, PartialEq, Eq)]
6#[cfg_attr(feature = "debug", derive(Debug))]
7#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
8#[repr(Rust, packed)]
9pub struct MemoryArg {
10 offset: u64,
11 mem_addr: MemAddr,
12}
13
14impl MemoryArg {
15 #[inline]
16 pub const fn new(offset: u64, mem_addr: MemAddr) -> Self {
17 Self { offset, mem_addr }
18 }
19
20 #[inline]
21 pub const fn offset(self) -> u64 {
22 self.offset
23 }
24
25 #[inline]
26 pub const fn mem_addr(self) -> MemAddr {
27 self.mem_addr
28 }
29}
30
31#[derive(Clone, Copy, PartialEq)]
32#[cfg_attr(feature = "debug", derive(Debug))]
33#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
34pub enum ConstInstruction {
35 I32Const(i32),
36 I64Const(i64),
37 F32Const(f32),
38 F64Const(f64),
39 V128Const(i128),
40 GlobalGet(GlobalAddr),
41 RefFunc(Option<FuncAddr>),
42 RefExtern(Option<ExternAddr>),
43 I32Add,
44 I32Sub,
45 I32Mul,
46 I64Add,
47 I64Sub,
48 I64Mul,
49}
50
51#[derive(Clone, Copy, PartialEq, Eq)]
53#[cfg_attr(feature = "debug", derive(Debug))]
54#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
55pub enum CmpOp {
56 Eq,
57 Ne,
58 LtS,
59 LtU,
60 GtS,
61 GtU,
62 LeS,
63 LeU,
64 GeS,
65 GeU,
66}
67
68#[derive(Clone, Copy, PartialEq, Eq)]
69#[cfg_attr(feature = "debug", derive(Debug))]
70#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
71pub enum BinOp {
72 IAdd,
73 ISub,
74 IMul,
75 IAnd,
76 IOr,
77 IXor,
78 IShl,
79 IShrS,
80 IShrU,
81 IRotl,
82 IRotr,
83 FAdd,
84 FSub,
85 FMul,
86 FDiv,
87 FMin,
88 FMax,
89 FCopysign,
90}
91
92#[derive(Clone, Copy, PartialEq, Eq)]
93#[cfg_attr(feature = "debug", derive(Debug))]
94#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
95pub enum BinOp128 {
96 And,
97 AndNot,
98 Or,
99 Xor,
100 I64x2Add,
101 I64x2Mul,
102}
103
104#[rustfmt::skip]
111#[derive(Clone, Copy, PartialEq)]
112#[cfg_attr(feature = "debug", derive(Debug))]
113#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
114pub enum Instruction {
115 LocalCopy32(LocalAddr, LocalAddr), LocalCopy64(LocalAddr, LocalAddr), LocalCopy128(LocalAddr, LocalAddr),
116 AddConst32(i32), AddConst64(i64),
117 IncLocal32(LocalAddr, i32), IncLocal64(LocalAddr, i64),
118 BinOpLocalLocal32(BinOp, LocalAddr, LocalAddr), BinOpLocalLocal64(BinOp, LocalAddr, LocalAddr),
120 BinOpLocalLocal128(BinOp128, LocalAddr, LocalAddr),
121 BinOpLocalLocalSet32(BinOp, LocalAddr, LocalAddr, LocalAddr),
122 BinOpLocalLocalSet64(BinOp, LocalAddr, LocalAddr, LocalAddr),
123 BinOpLocalLocalSet128(BinOp128, LocalAddr, LocalAddr, LocalAddr),
124 BinOpLocalLocalTee32(BinOp, LocalAddr, LocalAddr, LocalAddr),
125 BinOpLocalLocalTee64(BinOp, LocalAddr, LocalAddr, LocalAddr),
126 BinOpLocalLocalTee128(BinOp128, LocalAddr, LocalAddr, LocalAddr),
127 BinOpLocalConst32(BinOp, LocalAddr, i32), BinOpLocalConst64(BinOp, LocalAddr, i64),
128 BinOpLocalConst128(BinOp128, LocalAddr, ConstIdx),
129 BinOpLocalConstSet32(BinOp, LocalAddr, i32, LocalAddr),
130 BinOpLocalConstSet64(BinOp, LocalAddr, i64, LocalAddr),
131 BinOpLocalConstSet128(BinOp128, LocalAddr, ConstIdx, LocalAddr),
132 BinOpLocalConstTee32(BinOp, LocalAddr, i32, LocalAddr),
133 BinOpLocalConstTee64(BinOp, LocalAddr, i64, LocalAddr),
134 BinOpLocalConstTee128(BinOp128, LocalAddr, ConstIdx, LocalAddr),
135 BinOpStackGlobal32(BinOp, u32),
136 BinOpStackGlobal64(BinOp, u32),
137 SetLocalConst32(LocalAddr, i32), SetLocalConst64(LocalAddr, i64), SetLocalConst128(LocalAddr, ConstIdx),
138 StoreLocalLocal32(MemoryArg, u8, u8),
139 StoreLocalLocal64(MemoryArg, u8, u8),
140 StoreLocalLocal128(MemoryArg, u8, u8),
141 LoadLocal32(MemoryArg, u8),
142 LoadLocalTee32(MemoryArg, u8, u8),
143 LoadLocalSet32(MemoryArg, u8, u8),
144 LoadLocalTee128(MemoryArg, u8, u8),
145 LoadLocalSet128(MemoryArg, u8, u8),
146 AndConstTee32(i32, LocalAddr),
147 SubConstTee32(i32, LocalAddr),
148 AndConstTee64(i64, LocalAddr),
149 SubConstTee64(i64, LocalAddr),
150 MulAccLocal32(LocalAddr),
151 MulAccLocal64(LocalAddr),
152 FMulAccLocal32(LocalAddr),
153 FMulAccLocal64(LocalAddr),
154 I32Add3,
155 I64Add3,
156 FMaStoreF32(MemoryArg),
157 FMaStoreF64(MemoryArg),
158
159 Unreachable,
162 Nop,
163 MergeBarrier,
164 Jump(u32),
165 JumpIfZero32(u32),
166 JumpIfNonZero32(u32),
167 JumpIfZero64(u32),
168 JumpIfNonZero64(u32),
169 JumpIfLocalZero32 { target_ip: u32, local: LocalAddr },
170 JumpIfLocalNonZero32 { target_ip: u32, local: LocalAddr },
171 JumpIfLocalZero64 { target_ip: u32, local: LocalAddr },
172 JumpIfLocalNonZero64 { target_ip: u32, local: LocalAddr },
173 JumpCmpStackConst32 { target_ip: u32, imm: i32, op: CmpOp },
174 JumpCmpStackConst64 { target_ip: u32, imm: i64, op: CmpOp },
175 JumpCmpLocalConst32 { target_ip: u32, local: LocalAddr, imm: i32, op: CmpOp },
176 JumpCmpLocalConst64 { target_ip: u32, local: LocalAddr, imm: i32, op: CmpOp },
177 JumpCmpLocalLocal32 { target_ip: u32, left: LocalAddr, right: LocalAddr, op: CmpOp },
178 JumpCmpLocalLocal64 { target_ip: u32, left: LocalAddr, right: LocalAddr, op: CmpOp },
179 DropKeep { base32: u16, keep32: u8, base64: u16, keep64: u8, base128: u16, keep128: u8 },
180 DropKeep32(u16, u16),
181 DropKeep64(u16, u16),
182 DropKeep128(u16, u16),
183 BranchTable(u32, u32, u32), Return,
185 ReturnVoid,
186 Return32,
187 Return64,
188 Return128,
189 Call(FuncAddr),
190 CallSelf,
191 CallIndirect(TypeAddr, TableAddr),
192 ReturnCall(FuncAddr),
193 ReturnCallSelf,
194 ReturnCallIndirect(TypeAddr, TableAddr),
195
196 Drop32, Select32,
199 Drop64, Select64,
200 Drop128, Select128,
201 SelectMulti(ValueCounts),
202
203 GlobalGet(GlobalAddr),
206 LocalGet32(LocalAddr), LocalSet32(LocalAddr), LocalTee32(LocalAddr), GlobalSet32(GlobalAddr),
207 LocalGet64(LocalAddr), LocalSet64(LocalAddr), LocalTee64(LocalAddr), GlobalSet64(GlobalAddr),
208 LocalGet128(LocalAddr), LocalSet128(LocalAddr), LocalTee128(LocalAddr), GlobalSet128(GlobalAddr),
209
210 I32Load(MemoryArg),
212 I64Load(MemoryArg),
213 F32Load(MemoryArg),
214 F64Load(MemoryArg),
215 I32Load8S(MemoryArg),
216 I32Load8U(MemoryArg),
217 I32Load16S(MemoryArg),
218 I32Load16U(MemoryArg),
219 I64Load8S(MemoryArg),
220 I64Load8U(MemoryArg),
221 I64Load16S(MemoryArg),
222 I64Load16U(MemoryArg),
223 I64Load32S(MemoryArg),
224 I64Load32U(MemoryArg),
225 I32Store(MemoryArg),
226 I64Store(MemoryArg),
227 F32Store(MemoryArg),
228 F64Store(MemoryArg),
229 I32Store8(MemoryArg),
230 I32Store16(MemoryArg),
231 I64Store8(MemoryArg),
232 I64Store16(MemoryArg),
233 I64Store32(MemoryArg),
234 MemorySize(MemAddr),
235 MemoryGrow(MemAddr),
236
237 Const32(i32),
239 Const64(i64),
240
241 RefNull(WasmType),
243 RefFunc(FuncAddr),
244 RefIsNull,
245
246 I32Eqz, I32Eq, I32Ne, I32LtS, I32LtU, I32GtS, I32GtU, I32LeS, I32LeU, I32GeS, I32GeU,
249 I64Eqz, I64Eq, I64Ne, I64LtS, I64LtU, I64GtS, I64GtU, I64LeS, I64LeU, I64GeS, I64GeU,
250
251 F32Eq, F32Ne, F32Lt, F32Gt, F32Le, F32Ge,
253 F64Eq, F64Ne, F64Lt, F64Gt, F64Le, F64Ge,
254 I32Clz, I32Ctz, I32Popcnt, I32Add, I32Sub, I32Mul, I32DivS, I32DivU, I32RemS, I32RemU,
255 I64Clz, I64Ctz, I64Popcnt, I64Add, I64Sub, I64Mul, I64DivS, I64DivU, I64RemS, I64RemU,
256
257 I32And, I32Or, I32Xor, I32Shl, I32ShrS, I32ShrU, I32Rotl, I32Rotr,
259 I64And, I64Or, I64Xor, I64Shl, I64ShrS, I64ShrU, I64Rotl, I64Rotr,
260
261 F32Abs, F32Neg, F32Ceil, F32Floor, F32Trunc, F32Nearest, F32Sqrt, F32Add, F32Sub, F32Mul, F32Div, F32Min, F32Max, F32Copysign,
263 F64Abs, F64Neg, F64Ceil, F64Floor, F64Trunc, F64Nearest, F64Sqrt, F64Add, F64Sub, F64Mul, F64Div, F64Min, F64Max, F64Copysign,
264 I32WrapI64, I32TruncF32S, I32TruncF32U, I32TruncF64S, I32TruncF64U, I32Extend8S, I32Extend16S,
265 I64Extend8S, I64Extend16S, I64Extend32S, I64ExtendI32S, I64ExtendI32U, I64TruncF32S, I64TruncF32U, I64TruncF64S, I64TruncF64U,
266 F32ConvertI32S, F32ConvertI32U, F32ConvertI64S, F32ConvertI64U, F32DemoteF64,
267 F64ConvertI32S, F64ConvertI32U, F64ConvertI64S, F64ConvertI64U, F64PromoteF32,
268
269 I32TruncSatF32S, I32TruncSatF32U, I32TruncSatF64S, I32TruncSatF64U,
271 I64TruncSatF32S, I64TruncSatF32U, I64TruncSatF64S, I64TruncSatF64U,
272
273 TableInit(ElemAddr, TableAddr),
275 TableGet(TableAddr),
276 TableSet(TableAddr),
277 TableCopy { dst_table: TableAddr, src_table: TableAddr },
278 TableGrow(TableAddr),
279 TableSize(TableAddr),
280 TableFill(TableAddr),
281
282 MemoryInit(MemAddr, DataAddr),
284 MemoryCopy { dst_mem: MemAddr, src_mem: MemAddr },
285 MemoryFill(MemAddr),
286 MemoryFillImm(MemAddr, u8, i32),
287 DataDrop(DataAddr),
288 ElemDrop(ElemAddr),
289
290 I64Add128, I64Sub128, I64MulWideS, I64MulWideU,
292
293 V128Load(MemoryArg),
295 V128Load8x8S(MemoryArg), V128Load8x8U(MemoryArg),
296 V128Load16x4S(MemoryArg), V128Load16x4U(MemoryArg),
297 V128Load32x2S(MemoryArg), V128Load32x2U(MemoryArg),
298
299 V128Load8Splat(MemoryArg), V128Load16Splat(MemoryArg), V128Load32Splat(MemoryArg), V128Load64Splat(MemoryArg),
300 V128Load8Lane(MemoryArg, u8), V128Load16Lane(MemoryArg, u8), V128Load32Lane(MemoryArg, u8), V128Load64Lane(MemoryArg, u8),
301
302 V128Load32Zero(MemoryArg), V128Load64Zero(MemoryArg),
303
304 V128Store(MemoryArg), V128Store8Lane(MemoryArg, u8), V128Store16Lane(MemoryArg, u8), V128Store32Lane(MemoryArg, u8), V128Store64Lane(MemoryArg, u8),
305
306 I8x16Shuffle(ConstIdx),
307 Const128(ConstIdx),
308
309 I8x16ExtractLaneS(u8), I8x16ExtractLaneU(u8), I8x16ReplaceLane(u8),
310 I16x8ExtractLaneS(u8), I16x8ExtractLaneU(u8), I16x8ReplaceLane(u8),
311 I32x4ExtractLane(u8), I32x4ReplaceLane(u8),
312 I64x2ExtractLane(u8), I64x2ReplaceLane(u8),
313 F32x4ExtractLane(u8), F32x4ReplaceLane(u8),
314 F64x2ExtractLane(u8), F64x2ReplaceLane(u8),
315
316 V128Not, V128And, V128AndNot, V128Or, V128Xor, V128Bitselect, V128AnyTrue, I8x16Swizzle,
317 I8x16Splat, I8x16Eq, I8x16Ne, I8x16LtS, I8x16LtU, I8x16GtS, I8x16GtU, I8x16LeS, I8x16LeU, I8x16GeS, I8x16GeU,
318 I16x8Splat, I16x8Eq, I16x8Ne, I16x8LtS, I16x8LtU, I16x8GtS, I16x8GtU, I16x8LeS, I16x8LeU, I16x8GeS, I16x8GeU,
319 I32x4Splat, I32x4Eq, I32x4Ne, I32x4LtS, I32x4LtU, I32x4GtS, I32x4GtU, I32x4LeS, I32x4LeU, I32x4GeS, I32x4GeU,
320 I64x2Splat, I64x2Eq, I64x2Ne, I64x2LtS, I64x2GtS, I64x2LeS, I64x2GeS,
321 F32x4Splat, F32x4Eq, F32x4Ne, F32x4Lt, F32x4Gt, F32x4Le, F32x4Ge,
322 F64x2Splat, F64x2Eq, F64x2Ne, F64x2Lt, F64x2Gt, F64x2Le, F64x2Ge,
323
324 I8x16Abs, I8x16Neg, I8x16AllTrue, I8x16Bitmask, I8x16Shl, I8x16ShrS, I8x16ShrU, I8x16Add, I8x16Sub, I8x16MinS, I8x16MinU, I8x16MaxS, I8x16MaxU,
325 I16x8Abs, I16x8Neg, I16x8AllTrue, I16x8Bitmask, I16x8Shl, I16x8ShrS, I16x8ShrU, I16x8Add, I16x8Sub, I16x8MinS, I16x8MinU, I16x8MaxS, I16x8MaxU,
326 I32x4Abs, I32x4Neg, I32x4AllTrue, I32x4Bitmask, I32x4Shl, I32x4ShrS, I32x4ShrU, I32x4Add, I32x4Sub, I32x4MinS, I32x4MinU, I32x4MaxS, I32x4MaxU,
327 I64x2Abs, I64x2Neg, I64x2AllTrue, I64x2Bitmask, I64x2Shl, I64x2ShrS, I64x2ShrU, I64x2Add, I64x2Sub, I64x2Mul,
328
329 I8x16NarrowI16x8S, I8x16NarrowI16x8U, I8x16AddSatS, I8x16AddSatU, I8x16SubSatS, I8x16SubSatU, I8x16AvgrU,
330 I16x8NarrowI32x4S, I16x8NarrowI32x4U, I16x8AddSatS, I16x8AddSatU, I16x8SubSatS, I16x8SubSatU, I16x8AvgrU,
331
332 I16x8ExtAddPairwiseI8x16S, I16x8ExtAddPairwiseI8x16U, I16x8Mul,
333 I32x4ExtAddPairwiseI16x8S, I32x4ExtAddPairwiseI16x8U, I32x4Mul,
334
335 I16x8ExtMulLowI8x16S, I16x8ExtMulLowI8x16U, I16x8ExtMulHighI8x16S, I16x8ExtMulHighI8x16U,
336 I32x4ExtMulLowI16x8S, I32x4ExtMulLowI16x8U, I32x4ExtMulHighI16x8S, I32x4ExtMulHighI16x8U,
337 I64x2ExtMulLowI32x4S, I64x2ExtMulLowI32x4U, I64x2ExtMulHighI32x4S, I64x2ExtMulHighI32x4U,
338
339 I16x8ExtendLowI8x16S, I16x8ExtendLowI8x16U, I16x8ExtendHighI8x16S, I16x8ExtendHighI8x16U,
340 I32x4ExtendLowI16x8S, I32x4ExtendLowI16x8U, I32x4ExtendHighI16x8S, I32x4ExtendHighI16x8U,
341 I64x2ExtendLowI32x4S, I64x2ExtendLowI32x4U, I64x2ExtendHighI32x4S, I64x2ExtendHighI32x4U,
342
343 I8x16Popcnt, I16x8Q15MulrSatS, I32x4DotI16x8S,
344
345 F32x4Ceil, F32x4Floor, F32x4Trunc, F32x4Nearest, F32x4Abs, F32x4Neg, F32x4Sqrt, F32x4Add, F32x4Sub, F32x4Mul, F32x4Div, F32x4Min, F32x4Max, F32x4PMin, F32x4PMax,
346 F64x2Ceil, F64x2Floor, F64x2Trunc, F64x2Nearest, F64x2Abs, F64x2Neg, F64x2Sqrt, F64x2Add, F64x2Sub, F64x2Mul, F64x2Div, F64x2Min, F64x2Max, F64x2PMin, F64x2PMax,
347 I32x4TruncSatF32x4S, I32x4TruncSatF32x4U,
348 F32x4ConvertI32x4S, F32x4ConvertI32x4U,
349 I32x4TruncSatF64x2SZero, I32x4TruncSatF64x2UZero,
350 F64x2ConvertLowI32x4S, F64x2ConvertLowI32x4U,
351 F32x4DemoteF64x2Zero, F64x2PromoteLowF32x4,
352
353 I8x16RelaxedSwizzle,
355 I32x4RelaxedTruncF32x4S, I32x4RelaxedTruncF32x4U,
356 I32x4RelaxedTruncF64x2SZero, I32x4RelaxedTruncF64x2UZero,
357 F32x4RelaxedMadd, F32x4RelaxedNmadd,
358 F64x2RelaxedMadd, F64x2RelaxedNmadd,
359 I8x16RelaxedLaneselect,
360 I16x8RelaxedLaneselect,
361 I32x4RelaxedLaneselect,
362 I64x2RelaxedLaneselect,
363 F32x4RelaxedMin, F32x4RelaxedMax,
364 F64x2RelaxedMin, F64x2RelaxedMax,
365 I16x8RelaxedQ15mulrS,
366 I16x8RelaxedDotI8x16I7x16S,
367 I32x4RelaxedDotI8x16I7x16AddS
368}
369
370impl Instruction {
371 #[inline]
372 pub const fn memory_addr(&self) -> Option<MemAddr> {
373 match self {
374 Self::StoreLocalLocal32(arg, ..)
375 | Self::StoreLocalLocal64(arg, ..)
376 | Self::StoreLocalLocal128(arg, ..)
377 | Self::LoadLocal32(arg, ..)
378 | Self::LoadLocalTee32(arg, ..)
379 | Self::LoadLocalSet32(arg, ..)
380 | Self::LoadLocalTee128(arg, ..)
381 | Self::LoadLocalSet128(arg, ..)
382 | Self::I32Load(arg)
383 | Self::I64Load(arg)
384 | Self::F32Load(arg)
385 | Self::F64Load(arg)
386 | Self::I32Load8S(arg)
387 | Self::I32Load8U(arg)
388 | Self::I32Load16S(arg)
389 | Self::I32Load16U(arg)
390 | Self::I64Load8S(arg)
391 | Self::I64Load8U(arg)
392 | Self::I64Load16S(arg)
393 | Self::I64Load16U(arg)
394 | Self::I64Load32S(arg)
395 | Self::I64Load32U(arg)
396 | Self::I32Store(arg)
397 | Self::I64Store(arg)
398 | Self::F32Store(arg)
399 | Self::F64Store(arg)
400 | Self::FMaStoreF32(arg)
401 | Self::FMaStoreF64(arg)
402 | Self::I32Store8(arg)
403 | Self::I32Store16(arg)
404 | Self::I64Store8(arg)
405 | Self::I64Store16(arg)
406 | Self::I64Store32(arg)
407 | Self::V128Load(arg)
408 | Self::V128Load8x8S(arg)
409 | Self::V128Load8x8U(arg)
410 | Self::V128Load16x4S(arg)
411 | Self::V128Load16x4U(arg)
412 | Self::V128Load32x2S(arg)
413 | Self::V128Load32x2U(arg)
414 | Self::V128Load8Splat(arg)
415 | Self::V128Load16Splat(arg)
416 | Self::V128Load32Splat(arg)
417 | Self::V128Load64Splat(arg)
418 | Self::V128Load8Lane(arg, ..)
419 | Self::V128Load16Lane(arg, ..)
420 | Self::V128Load32Lane(arg, ..)
421 | Self::V128Load64Lane(arg, ..)
422 | Self::V128Load32Zero(arg)
423 | Self::V128Load64Zero(arg)
424 | Self::V128Store(arg)
425 | Self::V128Store8Lane(arg, ..)
426 | Self::V128Store16Lane(arg, ..)
427 | Self::V128Store32Lane(arg, ..)
428 | Self::V128Store64Lane(arg, ..) => Some(arg.mem_addr()),
429 Self::MemorySize(mem)
430 | Self::MemoryGrow(mem)
431 | Self::MemoryInit(mem, ..)
432 | Self::MemoryFill(mem)
433 | Self::MemoryFillImm(mem, ..) => Some(*mem),
434 Self::MemoryCopy { dst_mem, src_mem } => Some(if *dst_mem >= *src_mem { *dst_mem } else { *src_mem }),
435 _ => None,
436 }
437 }
438}
439
440#[cfg(test)]
441mod tests {
442 use super::Instruction;
443
444 #[test]
445 fn instruction_layout_size_is_stable() {
446 assert_eq!(core::mem::size_of::<Instruction>(), 16);
447 }
448}