Skip to main content

tinywasm_types/
instructions.rs

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