package interpreter import ( "fmt" "math" "strings" ) // unsignedInt represents unsigned 32-bit or 64-bit integers. type unsignedInt byte const ( unsignedInt32 unsignedInt = iota unsignedInt64 ) // String implements fmt.Stringer. func (s unsignedInt) String() (ret string) { switch s { case unsignedInt32: ret = "i32" case unsignedInt64: ret = "i64" } return } // signedInt represents signed or unsigned integers. type signedInt byte const ( signedInt32 signedInt = iota signedInt64 signedUint32 signedUint64 ) // String implements fmt.Stringer. func (s signedInt) String() (ret string) { switch s { case signedUint32: ret = "u32" case signedUint64: ret = "u64" case signedInt32: ret = "s32" case signedInt64: ret = "s64" } return } // float represents the scalar double or single precision floating points. type float byte const ( f32 float = iota f64 ) // String implements fmt.Stringer. func (s float) String() (ret string) { switch s { case f32: ret = "f32" case f64: ret = "f64" } return } // unsignedType is the union of unsignedInt, float and V128 vector type. type unsignedType byte const ( unsignedTypeI32 unsignedType = iota unsignedTypeI64 unsignedTypeF32 unsignedTypeF64 unsignedTypeV128 unsignedTypeUnknown ) // String implements fmt.Stringer. func (s unsignedType) String() (ret string) { switch s { case unsignedTypeI32: ret = "i32" case unsignedTypeI64: ret = "i64" case unsignedTypeF32: ret = "f32" case unsignedTypeF64: ret = "f64" case unsignedTypeV128: ret = "v128" case unsignedTypeUnknown: ret = "unknown" } return } // signedType is the union of signedInt and float types. type signedType byte const ( signedTypeInt32 signedType = iota signedTypeUint32 signedTypeInt64 signedTypeUint64 signedTypeFloat32 signedTypeFloat64 ) // String implements fmt.Stringer. func (s signedType) String() (ret string) { switch s { case signedTypeInt32: ret = "s32" case signedTypeUint32: ret = "u32" case signedTypeInt64: ret = "s64" case signedTypeUint64: ret = "u64" case signedTypeFloat32: ret = "f32" case signedTypeFloat64: ret = "f64" } return } // operationKind is the Kind of each implementation of Operation interface. type operationKind uint16 // String implements fmt.Stringer. func (o operationKind) String() (ret string) { switch o { case operationKindUnreachable: ret = "Unreachable" case operationKindLabel: ret = "label" case operationKindBr: ret = "Br" case operationKindBrIf: ret = "BrIf" case operationKindBrTable: ret = "BrTable" case operationKindCall: ret = "Call" case operationKindCallIndirect: ret = "CallIndirect" case operationKindDrop: ret = "Drop" case operationKindSelect: ret = "Select" case operationKindPick: ret = "Pick" case operationKindSet: ret = "Swap" case operationKindGlobalGet: ret = "GlobalGet" case operationKindGlobalSet: ret = "GlobalSet" case operationKindLoad: ret = "Load" case operationKindLoad8: ret = "Load8" case operationKindLoad16: ret = "Load16" case operationKindLoad32: ret = "Load32" case operationKindStore: ret = "Store" case operationKindStore8: ret = "Store8" case operationKindStore16: ret = "Store16" case operationKindStore32: ret = "Store32" case operationKindMemorySize: ret = "MemorySize" case operationKindMemoryGrow: ret = "MemoryGrow" case operationKindConstI32: ret = "ConstI32" case operationKindConstI64: ret = "ConstI64" case operationKindConstF32: ret = "ConstF32" case operationKindConstF64: ret = "ConstF64" case operationKindEq: ret = "Eq" case operationKindNe: ret = "Ne" case operationKindEqz: ret = "Eqz" case operationKindLt: ret = "Lt" case operationKindGt: ret = "Gt" case operationKindLe: ret = "Le" case operationKindGe: ret = "Ge" case operationKindAdd: ret = "Add" case operationKindSub: ret = "Sub" case operationKindMul: ret = "Mul" case operationKindClz: ret = "Clz" case operationKindCtz: ret = "Ctz" case operationKindPopcnt: ret = "Popcnt" case operationKindDiv: ret = "Div" case operationKindRem: ret = "Rem" case operationKindAnd: ret = "And" case operationKindOr: ret = "Or" case operationKindXor: ret = "Xor" case operationKindShl: ret = "Shl" case operationKindShr: ret = "Shr" case operationKindRotl: ret = "Rotl" case operationKindRotr: ret = "Rotr" case operationKindAbs: ret = "Abs" case operationKindNeg: ret = "Neg" case operationKindCeil: ret = "Ceil" case operationKindFloor: ret = "Floor" case operationKindTrunc: ret = "Trunc" case operationKindNearest: ret = "Nearest" case operationKindSqrt: ret = "Sqrt" case operationKindMin: ret = "Min" case operationKindMax: ret = "Max" case operationKindCopysign: ret = "Copysign" case operationKindI32WrapFromI64: ret = "I32WrapFromI64" case operationKindITruncFromF: ret = "ITruncFromF" case operationKindFConvertFromI: ret = "FConvertFromI" case operationKindF32DemoteFromF64: ret = "F32DemoteFromF64" case operationKindF64PromoteFromF32: ret = "F64PromoteFromF32" case operationKindI32ReinterpretFromF32: ret = "I32ReinterpretFromF32" case operationKindI64ReinterpretFromF64: ret = "I64ReinterpretFromF64" case operationKindF32ReinterpretFromI32: ret = "F32ReinterpretFromI32" case operationKindF64ReinterpretFromI64: ret = "F64ReinterpretFromI64" case operationKindExtend: ret = "Extend" case operationKindMemoryInit: ret = "MemoryInit" case operationKindDataDrop: ret = "DataDrop" case operationKindMemoryCopy: ret = "MemoryCopy" case operationKindMemoryFill: ret = "MemoryFill" case operationKindTableInit: ret = "TableInit" case operationKindElemDrop: ret = "ElemDrop" case operationKindTableCopy: ret = "TableCopy" case operationKindRefFunc: ret = "RefFunc" case operationKindTableGet: ret = "TableGet" case operationKindTableSet: ret = "TableSet" case operationKindTableSize: ret = "TableSize" case operationKindTableGrow: ret = "TableGrow" case operationKindTableFill: ret = "TableFill" case operationKindV128Const: ret = "ConstV128" case operationKindV128Add: ret = "V128Add" case operationKindV128Sub: ret = "V128Sub" case operationKindV128Load: ret = "V128Load" case operationKindV128LoadLane: ret = "V128LoadLane" case operationKindV128Store: ret = "V128Store" case operationKindV128StoreLane: ret = "V128StoreLane" case operationKindV128ExtractLane: ret = "V128ExtractLane" case operationKindV128ReplaceLane: ret = "V128ReplaceLane" case operationKindV128Splat: ret = "V128Splat" case operationKindV128Shuffle: ret = "V128Shuffle" case operationKindV128Swizzle: ret = "V128Swizzle" case operationKindV128AnyTrue: ret = "V128AnyTrue" case operationKindV128AllTrue: ret = "V128AllTrue" case operationKindV128And: ret = "V128And" case operationKindV128Not: ret = "V128Not" case operationKindV128Or: ret = "V128Or" case operationKindV128Xor: ret = "V128Xor" case operationKindV128Bitselect: ret = "V128Bitselect" case operationKindV128AndNot: ret = "V128AndNot" case operationKindV128BitMask: ret = "V128BitMask" case operationKindV128Shl: ret = "V128Shl" case operationKindV128Shr: ret = "V128Shr" case operationKindV128Cmp: ret = "V128Cmp" case operationKindSignExtend32From8: ret = "SignExtend32From8" case operationKindSignExtend32From16: ret = "SignExtend32From16" case operationKindSignExtend64From8: ret = "SignExtend64From8" case operationKindSignExtend64From16: ret = "SignExtend64From16" case operationKindSignExtend64From32: ret = "SignExtend64From32" case operationKindV128AddSat: ret = "V128AddSat" case operationKindV128SubSat: ret = "V128SubSat" case operationKindV128Mul: ret = "V128Mul" case operationKindV128Div: ret = "V128Div" case operationKindV128Neg: ret = "V128Neg" case operationKindV128Sqrt: ret = "V128Sqrt" case operationKindV128Abs: ret = "V128Abs" case operationKindV128Popcnt: ret = "V128Popcnt" case operationKindV128Min: ret = "V128Min" case operationKindV128Max: ret = "V128Max" case operationKindV128AvgrU: ret = "V128AvgrU" case operationKindV128Ceil: ret = "V128Ceil" case operationKindV128Floor: ret = "V128Floor" case operationKindV128Trunc: ret = "V128Trunc" case operationKindV128Nearest: ret = "V128Nearest" case operationKindV128Pmin: ret = "V128Pmin" case operationKindV128Pmax: ret = "V128Pmax" case operationKindV128Extend: ret = "V128Extend" case operationKindV128ExtMul: ret = "V128ExtMul" case operationKindV128Q15mulrSatS: ret = "V128Q15mulrSatS" case operationKindV128ExtAddPairwise: ret = "V128ExtAddPairwise" case operationKindV128FloatPromote: ret = "V128FloatPromote" case operationKindV128FloatDemote: ret = "V128FloatDemote" case operationKindV128FConvertFromI: ret = "V128FConvertFromI" case operationKindV128Dot: ret = "V128Dot" case operationKindV128Narrow: ret = "V128Narrow" case operationKindV128ITruncSatFromF: ret = "V128ITruncSatFromF" case operationKindBuiltinFunctionCheckExitCode: ret = "BuiltinFunctionCheckExitCode" case operationKindAtomicMemoryWait: ret = "operationKindAtomicMemoryWait" case operationKindAtomicMemoryNotify: ret = "operationKindAtomicMemoryNotify" case operationKindAtomicFence: ret = "operationKindAtomicFence" case operationKindAtomicLoad: ret = "operationKindAtomicLoad" case operationKindAtomicLoad8: ret = "operationKindAtomicLoad8" case operationKindAtomicLoad16: ret = "operationKindAtomicLoad16" case operationKindAtomicStore: ret = "operationKindAtomicStore" case operationKindAtomicStore8: ret = "operationKindAtomicStore8" case operationKindAtomicStore16: ret = "operationKindAtomicStore16" case operationKindAtomicRMW: ret = "operationKindAtomicRMW" case operationKindAtomicRMW8: ret = "operationKindAtomicRMW8" case operationKindAtomicRMW16: ret = "operationKindAtomicRMW16" case operationKindAtomicRMWCmpxchg: ret = "operationKindAtomicRMWCmpxchg" case operationKindAtomicRMW8Cmpxchg: ret = "operationKindAtomicRMW8Cmpxchg" case operationKindAtomicRMW16Cmpxchg: ret = "operationKindAtomicRMW16Cmpxchg" default: panic(fmt.Errorf("unknown operation %d", o)) } return } const ( // operationKindUnreachable is the Kind for NewOperationUnreachable. operationKindUnreachable operationKind = iota // operationKindLabel is the Kind for NewOperationLabel. operationKindLabel // operationKindBr is the Kind for NewOperationBr. operationKindBr // operationKindBrIf is the Kind for NewOperationBrIf. operationKindBrIf // operationKindBrTable is the Kind for NewOperationBrTable. operationKindBrTable // operationKindCall is the Kind for NewOperationCall. operationKindCall // operationKindCallIndirect is the Kind for NewOperationCallIndirect. operationKindCallIndirect // operationKindDrop is the Kind for NewOperationDrop. operationKindDrop // operationKindSelect is the Kind for NewOperationSelect. operationKindSelect // operationKindPick is the Kind for NewOperationPick. operationKindPick // operationKindSet is the Kind for NewOperationSet. operationKindSet // operationKindGlobalGet is the Kind for NewOperationGlobalGet. operationKindGlobalGet // operationKindGlobalSet is the Kind for NewOperationGlobalSet. operationKindGlobalSet // operationKindLoad is the Kind for NewOperationLoad. operationKindLoad // operationKindLoad8 is the Kind for NewOperationLoad8. operationKindLoad8 // operationKindLoad16 is the Kind for NewOperationLoad16. operationKindLoad16 // operationKindLoad32 is the Kind for NewOperationLoad32. operationKindLoad32 // operationKindStore is the Kind for NewOperationStore. operationKindStore // operationKindStore8 is the Kind for NewOperationStore8. operationKindStore8 // operationKindStore16 is the Kind for NewOperationStore16. operationKindStore16 // operationKindStore32 is the Kind for NewOperationStore32. operationKindStore32 // operationKindMemorySize is the Kind for NewOperationMemorySize. operationKindMemorySize // operationKindMemoryGrow is the Kind for NewOperationMemoryGrow. operationKindMemoryGrow // operationKindConstI32 is the Kind for NewOperationConstI32. operationKindConstI32 // operationKindConstI64 is the Kind for NewOperationConstI64. operationKindConstI64 // operationKindConstF32 is the Kind for NewOperationConstF32. operationKindConstF32 // operationKindConstF64 is the Kind for NewOperationConstF64. operationKindConstF64 // operationKindEq is the Kind for NewOperationEq. operationKindEq // operationKindNe is the Kind for NewOperationNe. operationKindNe // operationKindEqz is the Kind for NewOperationEqz. operationKindEqz // operationKindLt is the Kind for NewOperationLt. operationKindLt // operationKindGt is the Kind for NewOperationGt. operationKindGt // operationKindLe is the Kind for NewOperationLe. operationKindLe // operationKindGe is the Kind for NewOperationGe. operationKindGe // operationKindAdd is the Kind for NewOperationAdd. operationKindAdd // operationKindSub is the Kind for NewOperationSub. operationKindSub // operationKindMul is the Kind for NewOperationMul. operationKindMul // operationKindClz is the Kind for NewOperationClz. operationKindClz // operationKindCtz is the Kind for NewOperationCtz. operationKindCtz // operationKindPopcnt is the Kind for NewOperationPopcnt. operationKindPopcnt // operationKindDiv is the Kind for NewOperationDiv. operationKindDiv // operationKindRem is the Kind for NewOperationRem. operationKindRem // operationKindAnd is the Kind for NewOperationAnd. operationKindAnd // operationKindOr is the Kind for NewOperationOr. operationKindOr // operationKindXor is the Kind for NewOperationXor. operationKindXor // operationKindShl is the Kind for NewOperationShl. operationKindShl // operationKindShr is the Kind for NewOperationShr. operationKindShr // operationKindRotl is the Kind for NewOperationRotl. operationKindRotl // operationKindRotr is the Kind for NewOperationRotr. operationKindRotr // operationKindAbs is the Kind for NewOperationAbs. operationKindAbs // operationKindNeg is the Kind for NewOperationNeg. operationKindNeg // operationKindCeil is the Kind for NewOperationCeil. operationKindCeil // operationKindFloor is the Kind for NewOperationFloor. operationKindFloor // operationKindTrunc is the Kind for NewOperationTrunc. operationKindTrunc // operationKindNearest is the Kind for NewOperationNearest. operationKindNearest // operationKindSqrt is the Kind for NewOperationSqrt. operationKindSqrt // operationKindMin is the Kind for NewOperationMin. operationKindMin // operationKindMax is the Kind for NewOperationMax. operationKindMax // operationKindCopysign is the Kind for NewOperationCopysign. operationKindCopysign // operationKindI32WrapFromI64 is the Kind for NewOperationI32WrapFromI64. operationKindI32WrapFromI64 // operationKindITruncFromF is the Kind for NewOperationITruncFromF. operationKindITruncFromF // operationKindFConvertFromI is the Kind for NewOperationFConvertFromI. operationKindFConvertFromI // operationKindF32DemoteFromF64 is the Kind for NewOperationF32DemoteFromF64. operationKindF32DemoteFromF64 // operationKindF64PromoteFromF32 is the Kind for NewOperationF64PromoteFromF32. operationKindF64PromoteFromF32 // operationKindI32ReinterpretFromF32 is the Kind for NewOperationI32ReinterpretFromF32. operationKindI32ReinterpretFromF32 // operationKindI64ReinterpretFromF64 is the Kind for NewOperationI64ReinterpretFromF64. operationKindI64ReinterpretFromF64 // operationKindF32ReinterpretFromI32 is the Kind for NewOperationF32ReinterpretFromI32. operationKindF32ReinterpretFromI32 // operationKindF64ReinterpretFromI64 is the Kind for NewOperationF64ReinterpretFromI64. operationKindF64ReinterpretFromI64 // operationKindExtend is the Kind for NewOperationExtend. operationKindExtend // operationKindSignExtend32From8 is the Kind for NewOperationSignExtend32From8. operationKindSignExtend32From8 // operationKindSignExtend32From16 is the Kind for NewOperationSignExtend32From16. operationKindSignExtend32From16 // operationKindSignExtend64From8 is the Kind for NewOperationSignExtend64From8. operationKindSignExtend64From8 // operationKindSignExtend64From16 is the Kind for NewOperationSignExtend64From16. operationKindSignExtend64From16 // operationKindSignExtend64From32 is the Kind for NewOperationSignExtend64From32. operationKindSignExtend64From32 // operationKindMemoryInit is the Kind for NewOperationMemoryInit. operationKindMemoryInit // operationKindDataDrop is the Kind for NewOperationDataDrop. operationKindDataDrop // operationKindMemoryCopy is the Kind for NewOperationMemoryCopy. operationKindMemoryCopy // operationKindMemoryFill is the Kind for NewOperationMemoryFill. operationKindMemoryFill // operationKindTableInit is the Kind for NewOperationTableInit. operationKindTableInit // operationKindElemDrop is the Kind for NewOperationElemDrop. operationKindElemDrop // operationKindTableCopy is the Kind for NewOperationTableCopy. operationKindTableCopy // operationKindRefFunc is the Kind for NewOperationRefFunc. operationKindRefFunc // operationKindTableGet is the Kind for NewOperationTableGet. operationKindTableGet // operationKindTableSet is the Kind for NewOperationTableSet. operationKindTableSet // operationKindTableSize is the Kind for NewOperationTableSize. operationKindTableSize // operationKindTableGrow is the Kind for NewOperationTableGrow. operationKindTableGrow // operationKindTableFill is the Kind for NewOperationTableFill. operationKindTableFill // Vector value related instructions are prefixed by V128. // operationKindV128Const is the Kind for NewOperationV128Const. operationKindV128Const // operationKindV128Add is the Kind for NewOperationV128Add. operationKindV128Add // operationKindV128Sub is the Kind for NewOperationV128Sub. operationKindV128Sub // operationKindV128Load is the Kind for NewOperationV128Load. operationKindV128Load // operationKindV128LoadLane is the Kind for NewOperationV128LoadLane. operationKindV128LoadLane // operationKindV128Store is the Kind for NewOperationV128Store. operationKindV128Store // operationKindV128StoreLane is the Kind for NewOperationV128StoreLane. operationKindV128StoreLane // operationKindV128ExtractLane is the Kind for NewOperationV128ExtractLane. operationKindV128ExtractLane // operationKindV128ReplaceLane is the Kind for NewOperationV128ReplaceLane. operationKindV128ReplaceLane // operationKindV128Splat is the Kind for NewOperationV128Splat. operationKindV128Splat // operationKindV128Shuffle is the Kind for NewOperationV128Shuffle. operationKindV128Shuffle // operationKindV128Swizzle is the Kind for NewOperationV128Swizzle. operationKindV128Swizzle // operationKindV128AnyTrue is the Kind for NewOperationV128AnyTrue. operationKindV128AnyTrue // operationKindV128AllTrue is the Kind for NewOperationV128AllTrue. operationKindV128AllTrue // operationKindV128BitMask is the Kind for NewOperationV128BitMask. operationKindV128BitMask // operationKindV128And is the Kind for NewOperationV128And. operationKindV128And // operationKindV128Not is the Kind for NewOperationV128Not. operationKindV128Not // operationKindV128Or is the Kind for NewOperationV128Or. operationKindV128Or // operationKindV128Xor is the Kind for NewOperationV128Xor. operationKindV128Xor // operationKindV128Bitselect is the Kind for NewOperationV128Bitselect. operationKindV128Bitselect // operationKindV128AndNot is the Kind for NewOperationV128AndNot. operationKindV128AndNot // operationKindV128Shl is the Kind for NewOperationV128Shl. operationKindV128Shl // operationKindV128Shr is the Kind for NewOperationV128Shr. operationKindV128Shr // operationKindV128Cmp is the Kind for NewOperationV128Cmp. operationKindV128Cmp // operationKindV128AddSat is the Kind for NewOperationV128AddSat. operationKindV128AddSat // operationKindV128SubSat is the Kind for NewOperationV128SubSat. operationKindV128SubSat // operationKindV128Mul is the Kind for NewOperationV128Mul. operationKindV128Mul // operationKindV128Div is the Kind for NewOperationV128Div. operationKindV128Div // operationKindV128Neg is the Kind for NewOperationV128Neg. operationKindV128Neg // operationKindV128Sqrt is the Kind for NewOperationV128Sqrt. operationKindV128Sqrt // operationKindV128Abs is the Kind for NewOperationV128Abs. operationKindV128Abs // operationKindV128Popcnt is the Kind for NewOperationV128Popcnt. operationKindV128Popcnt // operationKindV128Min is the Kind for NewOperationV128Min. operationKindV128Min // operationKindV128Max is the Kind for NewOperationV128Max. operationKindV128Max // operationKindV128AvgrU is the Kind for NewOperationV128AvgrU. operationKindV128AvgrU // operationKindV128Pmin is the Kind for NewOperationV128Pmin. operationKindV128Pmin // operationKindV128Pmax is the Kind for NewOperationV128Pmax. operationKindV128Pmax // operationKindV128Ceil is the Kind for NewOperationV128Ceil. operationKindV128Ceil // operationKindV128Floor is the Kind for NewOperationV128Floor. operationKindV128Floor // operationKindV128Trunc is the Kind for NewOperationV128Trunc. operationKindV128Trunc // operationKindV128Nearest is the Kind for NewOperationV128Nearest. operationKindV128Nearest // operationKindV128Extend is the Kind for NewOperationV128Extend. operationKindV128Extend // operationKindV128ExtMul is the Kind for NewOperationV128ExtMul. operationKindV128ExtMul // operationKindV128Q15mulrSatS is the Kind for NewOperationV128Q15mulrSatS. operationKindV128Q15mulrSatS // operationKindV128ExtAddPairwise is the Kind for NewOperationV128ExtAddPairwise. operationKindV128ExtAddPairwise // operationKindV128FloatPromote is the Kind for NewOperationV128FloatPromote. operationKindV128FloatPromote // operationKindV128FloatDemote is the Kind for NewOperationV128FloatDemote. operationKindV128FloatDemote // operationKindV128FConvertFromI is the Kind for NewOperationV128FConvertFromI. operationKindV128FConvertFromI // operationKindV128Dot is the Kind for NewOperationV128Dot. operationKindV128Dot // operationKindV128Narrow is the Kind for NewOperationV128Narrow. operationKindV128Narrow // operationKindV128ITruncSatFromF is the Kind for NewOperationV128ITruncSatFromF. operationKindV128ITruncSatFromF // operationKindBuiltinFunctionCheckExitCode is the Kind for NewOperationBuiltinFunctionCheckExitCode. operationKindBuiltinFunctionCheckExitCode // operationKindAtomicMemoryWait is the kind for NewOperationAtomicMemoryWait. operationKindAtomicMemoryWait // operationKindAtomicMemoryNotify is the kind for NewOperationAtomicMemoryNotify. operationKindAtomicMemoryNotify // operationKindAtomicFence is the kind for NewOperationAtomicFence. operationKindAtomicFence // operationKindAtomicLoad is the kind for NewOperationAtomicLoad. operationKindAtomicLoad // operationKindAtomicLoad8 is the kind for NewOperationAtomicLoad8. operationKindAtomicLoad8 // operationKindAtomicLoad16 is the kind for NewOperationAtomicLoad16. operationKindAtomicLoad16 // operationKindAtomicStore is the kind for NewOperationAtomicStore. operationKindAtomicStore // operationKindAtomicStore8 is the kind for NewOperationAtomicStore8. operationKindAtomicStore8 // operationKindAtomicStore16 is the kind for NewOperationAtomicStore16. operationKindAtomicStore16 // operationKindAtomicRMW is the kind for NewOperationAtomicRMW. operationKindAtomicRMW // operationKindAtomicRMW8 is the kind for NewOperationAtomicRMW8. operationKindAtomicRMW8 // operationKindAtomicRMW16 is the kind for NewOperationAtomicRMW16. operationKindAtomicRMW16 // operationKindAtomicRMWCmpxchg is the kind for NewOperationAtomicRMWCmpxchg. operationKindAtomicRMWCmpxchg // operationKindAtomicRMW8Cmpxchg is the kind for NewOperationAtomicRMW8Cmpxchg. operationKindAtomicRMW8Cmpxchg // operationKindAtomicRMW16Cmpxchg is the kind for NewOperationAtomicRMW16Cmpxchg. operationKindAtomicRMW16Cmpxchg // operationKindEnd is always placed at the bottom of this iota definition to be used in the test. operationKindEnd ) // NewOperationBuiltinFunctionCheckExitCode is a constructor for unionOperation with Kind operationKindBuiltinFunctionCheckExitCode. // // OperationBuiltinFunctionCheckExitCode corresponds to the instruction to check the api.Module is already closed due to // context.DeadlineExceeded, context.Canceled, or the explicit call of CloseWithExitCode on api.Module. func newOperationBuiltinFunctionCheckExitCode() unionOperation { return unionOperation{Kind: operationKindBuiltinFunctionCheckExitCode} } // label is the unique identifier for each block in a single function in interpreterir // where "block" consists of multiple operations, and must End with branching operations // (e.g. operationKindBr or operationKindBrIf). type label uint64 // Kind returns the labelKind encoded in this label. func (l label) Kind() labelKind { return labelKind(uint32(l)) } // FrameID returns the frame id encoded in this label. func (l label) FrameID() int { return int(uint32(l >> 32)) } // NewLabel is a constructor for a label. func newLabel(kind labelKind, frameID uint32) label { return label(kind) | label(frameID)<<32 } // String implements fmt.Stringer. func (l label) String() (ret string) { frameID := l.FrameID() switch l.Kind() { case labelKindHeader: ret = fmt.Sprintf(".L%d", frameID) case labelKindElse: ret = fmt.Sprintf(".L%d_else", frameID) case labelKindContinuation: ret = fmt.Sprintf(".L%d_cont", frameID) case labelKindReturn: return ".return" } return } func (l label) IsReturnTarget() bool { return l.Kind() == labelKindReturn } // labelKind is the Kind of the label. type labelKind = byte const ( // labelKindHeader is the header for various blocks. For example, the "then" block of // wasm.OpcodeIfName in Wasm has the label of this Kind. labelKindHeader labelKind = iota // labelKindElse is the Kind of label for "else" block of wasm.OpcodeIfName in Wasm. labelKindElse // labelKindContinuation is the Kind of label which is the continuation of blocks. // For example, for wasm text like // (func // .... // (if (local.get 0) (then (nop)) (else (nop))) // return // ) // we have the continuation block (of if-block) corresponding to "return" opcode. labelKindContinuation labelKindReturn labelKindNum ) // unionOperation implements Operation and is the compilation (engine.lowerIR) result of a interpreterir.Operation. // // Not all operations result in a unionOperation, e.g. interpreterir.OperationI32ReinterpretFromF32, and some operations are // more complex than others, e.g. interpreterir.NewOperationBrTable. // // Note: This is a form of union type as it can store fields needed for any operation. Hence, most fields are opaque and // only relevant when in context of its kind. type unionOperation struct { // Kind determines how to interpret the other fields in this struct. Kind operationKind B1, B2 byte B3 bool U1, U2 uint64 U3 uint64 Us []uint64 } // String implements fmt.Stringer. func (o unionOperation) String() string { switch o.Kind { case operationKindUnreachable, operationKindSelect, operationKindMemorySize, operationKindMemoryGrow, operationKindI32WrapFromI64, operationKindF32DemoteFromF64, operationKindF64PromoteFromF32, operationKindI32ReinterpretFromF32, operationKindI64ReinterpretFromF64, operationKindF32ReinterpretFromI32, operationKindF64ReinterpretFromI64, operationKindSignExtend32From8, operationKindSignExtend32From16, operationKindSignExtend64From8, operationKindSignExtend64From16, operationKindSignExtend64From32, operationKindMemoryInit, operationKindDataDrop, operationKindMemoryCopy, operationKindMemoryFill, operationKindTableInit, operationKindElemDrop, operationKindTableCopy, operationKindRefFunc, operationKindTableGet, operationKindTableSet, operationKindTableSize, operationKindTableGrow, operationKindTableFill, operationKindBuiltinFunctionCheckExitCode: return o.Kind.String() case operationKindCall, operationKindGlobalGet, operationKindGlobalSet: return fmt.Sprintf("%s %d", o.Kind, o.B1) case operationKindLabel: return label(o.U1).String() case operationKindBr: return fmt.Sprintf("%s %s", o.Kind, label(o.U1).String()) case operationKindBrIf: thenTarget := label(o.U1) elseTarget := label(o.U2) return fmt.Sprintf("%s %s, %s", o.Kind, thenTarget, elseTarget) case operationKindBrTable: var targets []string var defaultLabel label if len(o.Us) > 0 { targets = make([]string, len(o.Us)-1) for i, t := range o.Us[1:] { targets[i] = label(t).String() } defaultLabel = label(o.Us[0]) } return fmt.Sprintf("%s [%s] %s", o.Kind, strings.Join(targets, ","), defaultLabel) case operationKindCallIndirect: return fmt.Sprintf("%s: type=%d, table=%d", o.Kind, o.U1, o.U2) case operationKindDrop: start := int64(o.U1) end := int64(o.U2) return fmt.Sprintf("%s %d..%d", o.Kind, start, end) case operationKindPick, operationKindSet: return fmt.Sprintf("%s %d (is_vector=%v)", o.Kind, o.U1, o.B3) case operationKindLoad, operationKindStore: return fmt.Sprintf("%s.%s (align=%d, offset=%d)", unsignedType(o.B1), o.Kind, o.U1, o.U2) case operationKindLoad8, operationKindLoad16: return fmt.Sprintf("%s.%s (align=%d, offset=%d)", signedType(o.B1), o.Kind, o.U1, o.U2) case operationKindStore8, operationKindStore16, operationKindStore32: return fmt.Sprintf("%s (align=%d, offset=%d)", o.Kind, o.U1, o.U2) case operationKindLoad32: var t string if o.B1 == 1 { t = "i64" } else { t = "u64" } return fmt.Sprintf("%s.%s (align=%d, offset=%d)", t, o.Kind, o.U1, o.U2) case operationKindEq, operationKindNe, operationKindAdd, operationKindSub, operationKindMul: return fmt.Sprintf("%s.%s", unsignedType(o.B1), o.Kind) case operationKindEqz, operationKindClz, operationKindCtz, operationKindPopcnt, operationKindAnd, operationKindOr, operationKindXor, operationKindShl, operationKindRotl, operationKindRotr: return fmt.Sprintf("%s.%s", unsignedInt(o.B1), o.Kind) case operationKindRem, operationKindShr: return fmt.Sprintf("%s.%s", signedInt(o.B1), o.Kind) case operationKindLt, operationKindGt, operationKindLe, operationKindGe, operationKindDiv: return fmt.Sprintf("%s.%s", signedType(o.B1), o.Kind) case operationKindAbs, operationKindNeg, operationKindCeil, operationKindFloor, operationKindTrunc, operationKindNearest, operationKindSqrt, operationKindMin, operationKindMax, operationKindCopysign: return fmt.Sprintf("%s.%s", float(o.B1), o.Kind) case operationKindConstI32, operationKindConstI64: return fmt.Sprintf("%s %#x", o.Kind, o.U1) case operationKindConstF32: return fmt.Sprintf("%s %f", o.Kind, math.Float32frombits(uint32(o.U1))) case operationKindConstF64: return fmt.Sprintf("%s %f", o.Kind, math.Float64frombits(o.U1)) case operationKindITruncFromF: return fmt.Sprintf("%s.%s.%s (non_trapping=%v)", signedInt(o.B2), o.Kind, float(o.B1), o.B3) case operationKindFConvertFromI: return fmt.Sprintf("%s.%s.%s", float(o.B2), o.Kind, signedInt(o.B1)) case operationKindExtend: var in, out string if o.B3 { in = "i32" out = "i64" } else { in = "u32" out = "u64" } return fmt.Sprintf("%s.%s.%s", out, o.Kind, in) case operationKindV128Const: return fmt.Sprintf("%s [%#x, %#x]", o.Kind, o.U1, o.U2) case operationKindV128Add, operationKindV128Sub: return fmt.Sprintf("%s (shape=%s)", o.Kind, shapeName(o.B1)) case operationKindV128Load, operationKindV128LoadLane, operationKindV128Store, operationKindV128StoreLane, operationKindV128ExtractLane, operationKindV128ReplaceLane, operationKindV128Splat, operationKindV128Shuffle, operationKindV128Swizzle, operationKindV128AnyTrue, operationKindV128AllTrue, operationKindV128BitMask, operationKindV128And, operationKindV128Not, operationKindV128Or, operationKindV128Xor, operationKindV128Bitselect, operationKindV128AndNot, operationKindV128Shl, operationKindV128Shr, operationKindV128Cmp, operationKindV128AddSat, operationKindV128SubSat, operationKindV128Mul, operationKindV128Div, operationKindV128Neg, operationKindV128Sqrt, operationKindV128Abs, operationKindV128Popcnt, operationKindV128Min, operationKindV128Max, operationKindV128AvgrU, operationKindV128Pmin, operationKindV128Pmax, operationKindV128Ceil, operationKindV128Floor, operationKindV128Trunc, operationKindV128Nearest, operationKindV128Extend, operationKindV128ExtMul, operationKindV128Q15mulrSatS, operationKindV128ExtAddPairwise, operationKindV128FloatPromote, operationKindV128FloatDemote, operationKindV128FConvertFromI, operationKindV128Dot, operationKindV128Narrow: return o.Kind.String() case operationKindV128ITruncSatFromF: if o.B3 { return fmt.Sprintf("%s.%sS", o.Kind, shapeName(o.B1)) } else { return fmt.Sprintf("%s.%sU", o.Kind, shapeName(o.B1)) } case operationKindAtomicMemoryWait, operationKindAtomicMemoryNotify, operationKindAtomicFence, operationKindAtomicLoad, operationKindAtomicLoad8, operationKindAtomicLoad16, operationKindAtomicStore, operationKindAtomicStore8, operationKindAtomicStore16, operationKindAtomicRMW, operationKindAtomicRMW8, operationKindAtomicRMW16, operationKindAtomicRMWCmpxchg, operationKindAtomicRMW8Cmpxchg, operationKindAtomicRMW16Cmpxchg: return o.Kind.String() default: panic(fmt.Sprintf("TODO: %v", o.Kind)) } } // NewOperationUnreachable is a constructor for unionOperation with operationKindUnreachable // // This corresponds to wasm.OpcodeUnreachable. // // The engines are expected to exit the execution with wasmruntime.ErrRuntimeUnreachable error. func newOperationUnreachable() unionOperation { return unionOperation{Kind: operationKindUnreachable} } // NewOperationLabel is a constructor for unionOperation with operationKindLabel. // // This is used to inform the engines of the beginning of a label. func newOperationLabel(label label) unionOperation { return unionOperation{Kind: operationKindLabel, U1: uint64(label)} } // NewOperationBr is a constructor for unionOperation with operationKindBr. // // The engines are expected to branch into U1 label. func newOperationBr(target label) unionOperation { return unionOperation{Kind: operationKindBr, U1: uint64(target)} } // NewOperationBrIf is a constructor for unionOperation with operationKindBrIf. // // The engines are expected to pop a value and branch into U1 label if the value equals 1. // Otherwise, the code branches into U2 label. func newOperationBrIf(thenTarget, elseTarget label, thenDrop inclusiveRange) unionOperation { return unionOperation{ Kind: operationKindBrIf, U1: uint64(thenTarget), U2: uint64(elseTarget), U3: thenDrop.AsU64(), } } // NewOperationBrTable is a constructor for unionOperation with operationKindBrTable. // // This corresponds to wasm.OpcodeBrTableName except that the label // here means the interpreterir level, not the ones of Wasm. // // The engines are expected to do the br_table operation based on the default (Us[len(Us)-1], Us[len(Us)-2]) and // targets (Us[:len(Us)-1], Rs[:len(Us)-1]). More precisely, this pops a value from the stack (called "index") // and decides which branch we go into next based on the value. // // For example, assume we have operations like {default: L_DEFAULT, targets: [L0, L1, L2]}. // If "index" >= len(defaults), then branch into the L_DEFAULT label. // Otherwise, we enter label of targets[index]. func newOperationBrTable(targetLabelsAndRanges []uint64) unionOperation { return unionOperation{ Kind: operationKindBrTable, Us: targetLabelsAndRanges, } } // NewOperationCall is a constructor for unionOperation with operationKindCall. // // This corresponds to wasm.OpcodeCallName, and engines are expected to // enter into a function whose index equals OperationCall.FunctionIndex. func newOperationCall(functionIndex uint32) unionOperation { return unionOperation{Kind: operationKindCall, U1: uint64(functionIndex)} } // NewOperationCallIndirect implements Operation. // // This corresponds to wasm.OpcodeCallIndirectName, and engines are expected to // consume the one value from the top of stack (called "offset"), // and make a function call against the function whose function address equals // Tables[OperationCallIndirect.TableIndex][offset]. // // Note: This is called indirect function call in the sense that the target function is indirectly // determined by the current state (top value) of the stack. // Therefore, two checks are performed at runtime before entering the target function: // 1) whether "offset" exceeds the length of table Tables[OperationCallIndirect.TableIndex]. // 2) whether the type of the function table[offset] matches the function type specified by OperationCallIndirect.TypeIndex. func newOperationCallIndirect(typeIndex, tableIndex uint32) unionOperation { return unionOperation{Kind: operationKindCallIndirect, U1: uint64(typeIndex), U2: uint64(tableIndex)} } // inclusiveRange is the range which spans across the value stack starting from the top to the bottom, and // both boundary are included in the range. type inclusiveRange struct { Start, End int32 } // AsU64 is be used to convert inclusiveRange to uint64 so that it can be stored in unionOperation. func (i inclusiveRange) AsU64() uint64 { return uint64(uint32(i.Start))<<32 | uint64(uint32(i.End)) } // inclusiveRangeFromU64 retrieves inclusiveRange from the given uint64 which is stored in unionOperation. func inclusiveRangeFromU64(v uint64) inclusiveRange { return inclusiveRange{ Start: int32(uint32(v >> 32)), End: int32(uint32(v)), } } // nopinclusiveRange is inclusiveRange which corresponds to no-operation. var nopinclusiveRange = inclusiveRange{Start: -1, End: -1} // NewOperationDrop is a constructor for unionOperation with operationKindDrop. // // The engines are expected to discard the values selected by NewOperationDrop.Depth which // starts from the top of the stack to the bottom. // // depth spans across the uint64 value stack at runtime to be dropped by this operation. func newOperationDrop(depth inclusiveRange) unionOperation { return unionOperation{Kind: operationKindDrop, U1: depth.AsU64()} } // NewOperationSelect is a constructor for unionOperation with operationKindSelect. // // This corresponds to wasm.OpcodeSelect. // // The engines are expected to pop three values, say [..., x2, x1, c], then if the value "c" equals zero, // "x1" is pushed back onto the stack and, otherwise "x2" is pushed back. // // isTargetVector true if the selection target value's type is wasm.ValueTypeV128. func newOperationSelect(isTargetVector bool) unionOperation { return unionOperation{Kind: operationKindSelect, B3: isTargetVector} } // NewOperationPick is a constructor for unionOperation with operationKindPick. // // The engines are expected to copy a value pointed by depth, and push the // copied value onto the top of the stack. // // depth is the location of the pick target in the uint64 value stack at runtime. // If isTargetVector=true, this points to the location of the lower 64-bits of the vector. func newOperationPick(depth int, isTargetVector bool) unionOperation { return unionOperation{Kind: operationKindPick, U1: uint64(depth), B3: isTargetVector} } // NewOperationSet is a constructor for unionOperation with operationKindSet. // // The engines are expected to set the top value of the stack to the location specified by // depth. // // depth is the location of the set target in the uint64 value stack at runtime. // If isTargetVector=true, this points the location of the lower 64-bits of the vector. func newOperationSet(depth int, isTargetVector bool) unionOperation { return unionOperation{Kind: operationKindSet, U1: uint64(depth), B3: isTargetVector} } // NewOperationGlobalGet is a constructor for unionOperation with operationKindGlobalGet. // // The engines are expected to read the global value specified by OperationGlobalGet.Index, // and push the copy of the value onto the stack. // // See wasm.OpcodeGlobalGet. func newOperationGlobalGet(index uint32) unionOperation { return unionOperation{Kind: operationKindGlobalGet, U1: uint64(index)} } // NewOperationGlobalSet is a constructor for unionOperation with operationKindGlobalSet. // // The engines are expected to consume the value from the top of the stack, // and write the value into the global specified by OperationGlobalSet.Index. // // See wasm.OpcodeGlobalSet. func newOperationGlobalSet(index uint32) unionOperation { return unionOperation{Kind: operationKindGlobalSet, U1: uint64(index)} } // memoryArg is the "memarg" to all memory instructions. // // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#memory-instructions%E2%91%A0 type memoryArg struct { // Alignment the expected alignment (expressed as the exponent of a power of 2). Default to the natural alignment. // // "Natural alignment" is defined here as the smallest power of two that can hold the size of the value type. Ex // wasm.ValueTypeI64 is encoded in 8 little-endian bytes. 2^3 = 8, so the natural alignment is three. Alignment uint32 // Offset is the address offset added to the instruction's dynamic address operand, yielding a 33-bit effective // address that is the zero-based index at which the memory is accessed. Default to zero. Offset uint32 } // NewOperationLoad is a constructor for unionOperation with operationKindLoad. // // This corresponds to wasm.OpcodeI32LoadName wasm.OpcodeI64LoadName wasm.OpcodeF32LoadName and wasm.OpcodeF64LoadName. // // The engines are expected to check the boundary of memory length, and exit the execution if this exceeds the boundary, // otherwise load the corresponding value following the semantics of the corresponding WebAssembly instruction. func newOperationLoad(unsignedType unsignedType, arg memoryArg) unionOperation { return unionOperation{Kind: operationKindLoad, B1: byte(unsignedType), U1: uint64(arg.Alignment), U2: uint64(arg.Offset)} } // NewOperationLoad8 is a constructor for unionOperation with operationKindLoad8. // // This corresponds to wasm.OpcodeI32Load8SName wasm.OpcodeI32Load8UName wasm.OpcodeI64Load8SName wasm.OpcodeI64Load8UName. // // The engines are expected to check the boundary of memory length, and exit the execution if this exceeds the boundary, // otherwise load the corresponding value following the semantics of the corresponding WebAssembly instruction. func newOperationLoad8(signedInt signedInt, arg memoryArg) unionOperation { return unionOperation{Kind: operationKindLoad8, B1: byte(signedInt), U1: uint64(arg.Alignment), U2: uint64(arg.Offset)} } // NewOperationLoad16 is a constructor for unionOperation with operationKindLoad16. // // This corresponds to wasm.OpcodeI32Load16SName wasm.OpcodeI32Load16UName wasm.OpcodeI64Load16SName wasm.OpcodeI64Load16UName. // // The engines are expected to check the boundary of memory length, and exit the execution if this exceeds the boundary, // otherwise load the corresponding value following the semantics of the corresponding WebAssembly instruction. func newOperationLoad16(signedInt signedInt, arg memoryArg) unionOperation { return unionOperation{Kind: operationKindLoad16, B1: byte(signedInt), U1: uint64(arg.Alignment), U2: uint64(arg.Offset)} } // NewOperationLoad32 is a constructor for unionOperation with operationKindLoad32. // // This corresponds to wasm.OpcodeI64Load32SName wasm.OpcodeI64Load32UName. // // The engines are expected to check the boundary of memory length, and exit the execution if this exceeds the boundary, // otherwise load the corresponding value following the semantics of the corresponding WebAssembly instruction. func newOperationLoad32(signed bool, arg memoryArg) unionOperation { sigB := byte(0) if signed { sigB = 1 } return unionOperation{Kind: operationKindLoad32, B1: sigB, U1: uint64(arg.Alignment), U2: uint64(arg.Offset)} } // NewOperationStore is a constructor for unionOperation with operationKindStore. // // # This corresponds to wasm.OpcodeI32StoreName wasm.OpcodeI64StoreName wasm.OpcodeF32StoreName wasm.OpcodeF64StoreName // // The engines are expected to check the boundary of memory length, and exit the execution if this exceeds the boundary, // otherwise store the corresponding value following the semantics of the corresponding WebAssembly instruction. func newOperationStore(unsignedType unsignedType, arg memoryArg) unionOperation { return unionOperation{Kind: operationKindStore, B1: byte(unsignedType), U1: uint64(arg.Alignment), U2: uint64(arg.Offset)} } // NewOperationStore8 is a constructor for unionOperation with operationKindStore8. // // # This corresponds to wasm.OpcodeI32Store8Name wasm.OpcodeI64Store8Name // // The engines are expected to check the boundary of memory length, and exit the execution if this exceeds the boundary, // otherwise store the corresponding value following the semantics of the corresponding WebAssembly instruction. func newOperationStore8(arg memoryArg) unionOperation { return unionOperation{Kind: operationKindStore8, U1: uint64(arg.Alignment), U2: uint64(arg.Offset)} } // NewOperationStore16 is a constructor for unionOperation with operationKindStore16. // // # This corresponds to wasm.OpcodeI32Store16Name wasm.OpcodeI64Store16Name // // The engines are expected to check the boundary of memory length, and exit the execution if this exceeds the boundary, // otherwise store the corresponding value following the semantics of the corresponding WebAssembly instruction. func newOperationStore16(arg memoryArg) unionOperation { return unionOperation{Kind: operationKindStore16, U1: uint64(arg.Alignment), U2: uint64(arg.Offset)} } // NewOperationStore32 is a constructor for unionOperation with operationKindStore32. // // # This corresponds to wasm.OpcodeI64Store32Name // // The engines are expected to check the boundary of memory length, and exit the execution if this exceeds the boundary, // otherwise store the corresponding value following the semantics of the corresponding WebAssembly instruction. func newOperationStore32(arg memoryArg) unionOperation { return unionOperation{Kind: operationKindStore32, U1: uint64(arg.Alignment), U2: uint64(arg.Offset)} } // NewOperationMemorySize is a constructor for unionOperation with operationKindMemorySize. // // This corresponds to wasm.OpcodeMemorySize. // // The engines are expected to push the current page size of the memory onto the stack. func newOperationMemorySize() unionOperation { return unionOperation{Kind: operationKindMemorySize} } // NewOperationMemoryGrow is a constructor for unionOperation with operationKindMemoryGrow. // // This corresponds to wasm.OpcodeMemoryGrow. // // The engines are expected to pop one value from the top of the stack, then // execute wasm.MemoryInstance Grow with the value, and push the previous // page size of the memory onto the stack. func newOperationMemoryGrow() unionOperation { return unionOperation{Kind: operationKindMemoryGrow} } // NewOperationConstI32 is a constructor for unionOperation with OperationConstI32. // // This corresponds to wasm.OpcodeI32Const. func newOperationConstI32(value uint32) unionOperation { return unionOperation{Kind: operationKindConstI32, U1: uint64(value)} } // NewOperationConstI64 is a constructor for unionOperation with OperationConstI64. // // This corresponds to wasm.OpcodeI64Const. func newOperationConstI64(value uint64) unionOperation { return unionOperation{Kind: operationKindConstI64, U1: value} } // NewOperationConstF32 is a constructor for unionOperation with OperationConstF32. // // This corresponds to wasm.OpcodeF32Const. func newOperationConstF32(value float32) unionOperation { return unionOperation{Kind: operationKindConstF32, U1: uint64(math.Float32bits(value))} } // NewOperationConstF64 is a constructor for unionOperation with OperationConstF64. // // This corresponds to wasm.OpcodeF64Const. func newOperationConstF64(value float64) unionOperation { return unionOperation{Kind: operationKindConstF64, U1: math.Float64bits(value)} } // NewOperationEq is a constructor for unionOperation with operationKindEq. // // This corresponds to wasm.OpcodeI32EqName wasm.OpcodeI64EqName wasm.OpcodeF32EqName wasm.OpcodeF64EqName func newOperationEq(b unsignedType) unionOperation { return unionOperation{Kind: operationKindEq, B1: byte(b)} } // NewOperationNe is a constructor for unionOperation with operationKindNe. // // This corresponds to wasm.OpcodeI32NeName wasm.OpcodeI64NeName wasm.OpcodeF32NeName wasm.OpcodeF64NeName func newOperationNe(b unsignedType) unionOperation { return unionOperation{Kind: operationKindNe, B1: byte(b)} } // NewOperationEqz is a constructor for unionOperation with operationKindEqz. // // This corresponds to wasm.OpcodeI32EqzName wasm.OpcodeI64EqzName func newOperationEqz(b unsignedInt) unionOperation { return unionOperation{Kind: operationKindEqz, B1: byte(b)} } // NewOperationLt is a constructor for unionOperation with operationKindLt. // // This corresponds to wasm.OpcodeI32LtS wasm.OpcodeI32LtU wasm.OpcodeI64LtS wasm.OpcodeI64LtU wasm.OpcodeF32Lt wasm.OpcodeF64Lt func newOperationLt(b signedType) unionOperation { return unionOperation{Kind: operationKindLt, B1: byte(b)} } // NewOperationGt is a constructor for unionOperation with operationKindGt. // // This corresponds to wasm.OpcodeI32GtS wasm.OpcodeI32GtU wasm.OpcodeI64GtS wasm.OpcodeI64GtU wasm.OpcodeF32Gt wasm.OpcodeF64Gt func newOperationGt(b signedType) unionOperation { return unionOperation{Kind: operationKindGt, B1: byte(b)} } // NewOperationLe is a constructor for unionOperation with operationKindLe. // // This corresponds to wasm.OpcodeI32LeS wasm.OpcodeI32LeU wasm.OpcodeI64LeS wasm.OpcodeI64LeU wasm.OpcodeF32Le wasm.OpcodeF64Le func newOperationLe(b signedType) unionOperation { return unionOperation{Kind: operationKindLe, B1: byte(b)} } // NewOperationGe is a constructor for unionOperation with operationKindGe. // // This corresponds to wasm.OpcodeI32GeS wasm.OpcodeI32GeU wasm.OpcodeI64GeS wasm.OpcodeI64GeU wasm.OpcodeF32Ge wasm.OpcodeF64Ge // NewOperationGe is the constructor for OperationGe func newOperationGe(b signedType) unionOperation { return unionOperation{Kind: operationKindGe, B1: byte(b)} } // NewOperationAdd is a constructor for unionOperation with operationKindAdd. // // This corresponds to wasm.OpcodeI32AddName wasm.OpcodeI64AddName wasm.OpcodeF32AddName wasm.OpcodeF64AddName. func newOperationAdd(b unsignedType) unionOperation { return unionOperation{Kind: operationKindAdd, B1: byte(b)} } // NewOperationSub is a constructor for unionOperation with operationKindSub. // // This corresponds to wasm.OpcodeI32SubName wasm.OpcodeI64SubName wasm.OpcodeF32SubName wasm.OpcodeF64SubName. func newOperationSub(b unsignedType) unionOperation { return unionOperation{Kind: operationKindSub, B1: byte(b)} } // NewOperationMul is a constructor for unionOperation with wperationKindMul. // // This corresponds to wasm.OpcodeI32MulName wasm.OpcodeI64MulName wasm.OpcodeF32MulName wasm.OpcodeF64MulName. // NewOperationMul is the constructor for OperationMul func newOperationMul(b unsignedType) unionOperation { return unionOperation{Kind: operationKindMul, B1: byte(b)} } // NewOperationClz is a constructor for unionOperation with operationKindClz. // // This corresponds to wasm.OpcodeI32ClzName wasm.OpcodeI64ClzName. // // The engines are expected to count up the leading zeros in the // current top of the stack, and push the count result. // For example, stack of [..., 0x00_ff_ff_ff] results in [..., 8]. // See wasm.OpcodeI32Clz wasm.OpcodeI64Clz func newOperationClz(b unsignedInt) unionOperation { return unionOperation{Kind: operationKindClz, B1: byte(b)} } // NewOperationCtz is a constructor for unionOperation with operationKindCtz. // // This corresponds to wasm.OpcodeI32CtzName wasm.OpcodeI64CtzName. // // The engines are expected to count up the trailing zeros in the // current top of the stack, and push the count result. // For example, stack of [..., 0xff_ff_ff_00] results in [..., 8]. func newOperationCtz(b unsignedInt) unionOperation { return unionOperation{Kind: operationKindCtz, B1: byte(b)} } // NewOperationPopcnt is a constructor for unionOperation with operationKindPopcnt. // // This corresponds to wasm.OpcodeI32PopcntName wasm.OpcodeI64PopcntName. // // The engines are expected to count up the number of set bits in the // current top of the stack, and push the count result. // For example, stack of [..., 0b00_00_00_11] results in [..., 2]. func newOperationPopcnt(b unsignedInt) unionOperation { return unionOperation{Kind: operationKindPopcnt, B1: byte(b)} } // NewOperationDiv is a constructor for unionOperation with operationKindDiv. // // This corresponds to wasm.OpcodeI32DivS wasm.OpcodeI32DivU wasm.OpcodeI64DivS // // wasm.OpcodeI64DivU wasm.OpcodeF32Div wasm.OpcodeF64Div. func newOperationDiv(b signedType) unionOperation { return unionOperation{Kind: operationKindDiv, B1: byte(b)} } // NewOperationRem is a constructor for unionOperation with operationKindRem. // // This corresponds to wasm.OpcodeI32RemS wasm.OpcodeI32RemU wasm.OpcodeI64RemS wasm.OpcodeI64RemU. // // The engines are expected to perform division on the top // two values of integer type on the stack and puts the remainder of the result // onto the stack. For example, stack [..., 10, 3] results in [..., 1] where // the quotient is discarded. // NewOperationRem is the constructor for OperationRem func newOperationRem(b signedInt) unionOperation { return unionOperation{Kind: operationKindRem, B1: byte(b)} } // NewOperationAnd is a constructor for unionOperation with operationKindAnd. // // # This corresponds to wasm.OpcodeI32AndName wasm.OpcodeI64AndName // // The engines are expected to perform "And" operation on // top two values on the stack, and pushes the result. func newOperationAnd(b unsignedInt) unionOperation { return unionOperation{Kind: operationKindAnd, B1: byte(b)} } // NewOperationOr is a constructor for unionOperation with operationKindOr. // // # This corresponds to wasm.OpcodeI32OrName wasm.OpcodeI64OrName // // The engines are expected to perform "Or" operation on // top two values on the stack, and pushes the result. func newOperationOr(b unsignedInt) unionOperation { return unionOperation{Kind: operationKindOr, B1: byte(b)} } // NewOperationXor is a constructor for unionOperation with operationKindXor. // // # This corresponds to wasm.OpcodeI32XorName wasm.OpcodeI64XorName // // The engines are expected to perform "Xor" operation on // top two values on the stack, and pushes the result. func newOperationXor(b unsignedInt) unionOperation { return unionOperation{Kind: operationKindXor, B1: byte(b)} } // NewOperationShl is a constructor for unionOperation with operationKindShl. // // # This corresponds to wasm.OpcodeI32ShlName wasm.OpcodeI64ShlName // // The engines are expected to perform "Shl" operation on // top two values on the stack, and pushes the result. func newOperationShl(b unsignedInt) unionOperation { return unionOperation{Kind: operationKindShl, B1: byte(b)} } // NewOperationShr is a constructor for unionOperation with operationKindShr. // // # This corresponds to wasm.OpcodeI32ShrSName wasm.OpcodeI32ShrUName wasm.OpcodeI64ShrSName wasm.OpcodeI64ShrUName // // If OperationShr.Type is signed integer, then, the engines are expected to perform arithmetic right shift on the two // top values on the stack, otherwise do the logical right shift. func newOperationShr(b signedInt) unionOperation { return unionOperation{Kind: operationKindShr, B1: byte(b)} } // NewOperationRotl is a constructor for unionOperation with operationKindRotl. // // # This corresponds to wasm.OpcodeI32RotlName wasm.OpcodeI64RotlName // // The engines are expected to perform "Rotl" operation on // top two values on the stack, and pushes the result. func newOperationRotl(b unsignedInt) unionOperation { return unionOperation{Kind: operationKindRotl, B1: byte(b)} } // NewOperationRotr is a constructor for unionOperation with operationKindRotr. // // # This corresponds to wasm.OpcodeI32RotrName wasm.OpcodeI64RotrName // // The engines are expected to perform "Rotr" operation on // top two values on the stack, and pushes the result. func newOperationRotr(b unsignedInt) unionOperation { return unionOperation{Kind: operationKindRotr, B1: byte(b)} } // NewOperationAbs is a constructor for unionOperation with operationKindAbs. // // This corresponds to wasm.OpcodeF32Abs wasm.OpcodeF64Abs func newOperationAbs(b float) unionOperation { return unionOperation{Kind: operationKindAbs, B1: byte(b)} } // NewOperationNeg is a constructor for unionOperation with operationKindNeg. // // This corresponds to wasm.OpcodeF32Neg wasm.OpcodeF64Neg func newOperationNeg(b float) unionOperation { return unionOperation{Kind: operationKindNeg, B1: byte(b)} } // NewOperationCeil is a constructor for unionOperation with operationKindCeil. // // This corresponds to wasm.OpcodeF32CeilName wasm.OpcodeF64CeilName func newOperationCeil(b float) unionOperation { return unionOperation{Kind: operationKindCeil, B1: byte(b)} } // NewOperationFloor is a constructor for unionOperation with operationKindFloor. // // This corresponds to wasm.OpcodeF32FloorName wasm.OpcodeF64FloorName func newOperationFloor(b float) unionOperation { return unionOperation{Kind: operationKindFloor, B1: byte(b)} } // NewOperationTrunc is a constructor for unionOperation with operationKindTrunc. // // This corresponds to wasm.OpcodeF32TruncName wasm.OpcodeF64TruncName func newOperationTrunc(b float) unionOperation { return unionOperation{Kind: operationKindTrunc, B1: byte(b)} } // NewOperationNearest is a constructor for unionOperation with operationKindNearest. // // # This corresponds to wasm.OpcodeF32NearestName wasm.OpcodeF64NearestName // // Note: this is *not* equivalent to math.Round and instead has the same // the semantics of LLVM's rint intrinsic. See https://llvm.org/docs/LangRef.html#llvm-rint-intrinsic. // For example, math.Round(-4.5) produces -5 while we want to produce -4. func newOperationNearest(b float) unionOperation { return unionOperation{Kind: operationKindNearest, B1: byte(b)} } // NewOperationSqrt is a constructor for unionOperation with operationKindSqrt. // // This corresponds to wasm.OpcodeF32SqrtName wasm.OpcodeF64SqrtName func newOperationSqrt(b float) unionOperation { return unionOperation{Kind: operationKindSqrt, B1: byte(b)} } // NewOperationMin is a constructor for unionOperation with operationKindMin. // // # This corresponds to wasm.OpcodeF32MinName wasm.OpcodeF64MinName // // The engines are expected to pop two values from the stack, and push back the maximum of // these two values onto the stack. For example, stack [..., 100.1, 1.9] results in [..., 1.9]. // // Note: WebAssembly specifies that min/max must always return NaN if one of values is NaN, // which is a different behavior different from math.Min. func newOperationMin(b float) unionOperation { return unionOperation{Kind: operationKindMin, B1: byte(b)} } // NewOperationMax is a constructor for unionOperation with operationKindMax. // // # This corresponds to wasm.OpcodeF32MaxName wasm.OpcodeF64MaxName // // The engines are expected to pop two values from the stack, and push back the maximum of // these two values onto the stack. For example, stack [..., 100.1, 1.9] results in [..., 100.1]. // // Note: WebAssembly specifies that min/max must always return NaN if one of values is NaN, // which is a different behavior different from math.Max. func newOperationMax(b float) unionOperation { return unionOperation{Kind: operationKindMax, B1: byte(b)} } // NewOperationCopysign is a constructor for unionOperation with operationKindCopysign. // // # This corresponds to wasm.OpcodeF32CopysignName wasm.OpcodeF64CopysignName // // The engines are expected to pop two float values from the stack, and copy the signbit of // the first-popped value to the last one. // For example, stack [..., 1.213, -5.0] results in [..., -1.213]. func newOperationCopysign(b float) unionOperation { return unionOperation{Kind: operationKindCopysign, B1: byte(b)} } // NewOperationI32WrapFromI64 is a constructor for unionOperation with operationKindI32WrapFromI64. // // This corresponds to wasm.OpcodeI32WrapI64 and equivalent to uint64(uint32(v)) in Go. // // The engines are expected to replace the 64-bit int on top of the stack // with the corresponding 32-bit integer. func newOperationI32WrapFromI64() unionOperation { return unionOperation{Kind: operationKindI32WrapFromI64} } // NewOperationITruncFromF is a constructor for unionOperation with operationKindITruncFromF. // // This corresponds to // // wasm.OpcodeI32TruncF32SName wasm.OpcodeI32TruncF32UName wasm.OpcodeI32TruncF64SName // wasm.OpcodeI32TruncF64UName wasm.OpcodeI64TruncF32SName wasm.OpcodeI64TruncF32UName wasm.OpcodeI64TruncF64SName // wasm.OpcodeI64TruncF64UName. wasm.OpcodeI32TruncSatF32SName wasm.OpcodeI32TruncSatF32UName // wasm.OpcodeI32TruncSatF64SName wasm.OpcodeI32TruncSatF64UName wasm.OpcodeI64TruncSatF32SName // wasm.OpcodeI64TruncSatF32UName wasm.OpcodeI64TruncSatF64SName wasm.OpcodeI64TruncSatF64UName // // See [1] and [2] for when we encounter undefined behavior in the WebAssembly specification if NewOperationITruncFromF.NonTrapping == false. // To summarize, if the source float value is NaN or doesn't fit in the destination range of integers (incl. +=Inf), // then the runtime behavior is undefined. In wazero, the engines are expected to exit the execution in these undefined cases with // wasmruntime.ErrRuntimeInvalidConversionToInteger error. // // [1] https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#-hrefop-trunc-umathrmtruncmathsfu_m-n-z for unsigned integers. // [2] https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#-hrefop-trunc-smathrmtruncmathsfs_m-n-z for signed integers. // // nonTrapping true if this conversion is "nontrapping" in the sense of the // https://github.com/WebAssembly/spec/blob/ce4b6c4d47eb06098cc7ab2e81f24748da822f20/proposals/nontrapping-float-to-int-conversion/Overview.md func newOperationITruncFromF(inputType float, outputType signedInt, nonTrapping bool) unionOperation { return unionOperation{ Kind: operationKindITruncFromF, B1: byte(inputType), B2: byte(outputType), B3: nonTrapping, } } // NewOperationFConvertFromI is a constructor for unionOperation with operationKindFConvertFromI. // // This corresponds to // // wasm.OpcodeF32ConvertI32SName wasm.OpcodeF32ConvertI32UName wasm.OpcodeF32ConvertI64SName wasm.OpcodeF32ConvertI64UName // wasm.OpcodeF64ConvertI32SName wasm.OpcodeF64ConvertI32UName wasm.OpcodeF64ConvertI64SName wasm.OpcodeF64ConvertI64UName // // and equivalent to float32(uint32(x)), float32(int32(x)), etc in Go. func newOperationFConvertFromI(inputType signedInt, outputType float) unionOperation { return unionOperation{ Kind: operationKindFConvertFromI, B1: byte(inputType), B2: byte(outputType), } } // NewOperationF32DemoteFromF64 is a constructor for unionOperation with operationKindF32DemoteFromF64. // // This corresponds to wasm.OpcodeF32DemoteF64 and is equivalent float32(float64(v)). func newOperationF32DemoteFromF64() unionOperation { return unionOperation{Kind: operationKindF32DemoteFromF64} } // NewOperationF64PromoteFromF32 is a constructor for unionOperation with operationKindF64PromoteFromF32. // // This corresponds to wasm.OpcodeF64PromoteF32 and is equivalent float64(float32(v)). func newOperationF64PromoteFromF32() unionOperation { return unionOperation{Kind: operationKindF64PromoteFromF32} } // NewOperationI32ReinterpretFromF32 is a constructor for unionOperation with operationKindI32ReinterpretFromF32. // // This corresponds to wasm.OpcodeI32ReinterpretF32Name. func newOperationI32ReinterpretFromF32() unionOperation { return unionOperation{Kind: operationKindI32ReinterpretFromF32} } // NewOperationI64ReinterpretFromF64 is a constructor for unionOperation with operationKindI64ReinterpretFromF64. // // This corresponds to wasm.OpcodeI64ReinterpretF64Name. func newOperationI64ReinterpretFromF64() unionOperation { return unionOperation{Kind: operationKindI64ReinterpretFromF64} } // NewOperationF32ReinterpretFromI32 is a constructor for unionOperation with operationKindF32ReinterpretFromI32. // // This corresponds to wasm.OpcodeF32ReinterpretI32Name. func newOperationF32ReinterpretFromI32() unionOperation { return unionOperation{Kind: operationKindF32ReinterpretFromI32} } // NewOperationF64ReinterpretFromI64 is a constructor for unionOperation with operationKindF64ReinterpretFromI64. // // This corresponds to wasm.OpcodeF64ReinterpretI64Name. func newOperationF64ReinterpretFromI64() unionOperation { return unionOperation{Kind: operationKindF64ReinterpretFromI64} } // NewOperationExtend is a constructor for unionOperation with operationKindExtend. // // # This corresponds to wasm.OpcodeI64ExtendI32SName wasm.OpcodeI64ExtendI32UName // // The engines are expected to extend the 32-bit signed or unsigned int on top of the stack // as a 64-bit integer of corresponding signedness. For unsigned case, this is just reinterpreting the // underlying bit pattern as 64-bit integer. For signed case, this is sign-extension which preserves the // original integer's sign. func newOperationExtend(signed bool) unionOperation { op := unionOperation{Kind: operationKindExtend} if signed { op.B1 = 1 } return op } // NewOperationSignExtend32From8 is a constructor for unionOperation with operationKindSignExtend32From8. // // This corresponds to wasm.OpcodeI32Extend8SName. // // The engines are expected to sign-extend the first 8-bits of 32-bit in as signed 32-bit int. func newOperationSignExtend32From8() unionOperation { return unionOperation{Kind: operationKindSignExtend32From8} } // NewOperationSignExtend32From16 is a constructor for unionOperation with operationKindSignExtend32From16. // // This corresponds to wasm.OpcodeI32Extend16SName. // // The engines are expected to sign-extend the first 16-bits of 32-bit in as signed 32-bit int. func newOperationSignExtend32From16() unionOperation { return unionOperation{Kind: operationKindSignExtend32From16} } // NewOperationSignExtend64From8 is a constructor for unionOperation with operationKindSignExtend64From8. // // This corresponds to wasm.OpcodeI64Extend8SName. // // The engines are expected to sign-extend the first 8-bits of 64-bit in as signed 32-bit int. func newOperationSignExtend64From8() unionOperation { return unionOperation{Kind: operationKindSignExtend64From8} } // NewOperationSignExtend64From16 is a constructor for unionOperation with operationKindSignExtend64From16. // // This corresponds to wasm.OpcodeI64Extend16SName. // // The engines are expected to sign-extend the first 16-bits of 64-bit in as signed 32-bit int. func newOperationSignExtend64From16() unionOperation { return unionOperation{Kind: operationKindSignExtend64From16} } // NewOperationSignExtend64From32 is a constructor for unionOperation with operationKindSignExtend64From32. // // This corresponds to wasm.OpcodeI64Extend32SName. // // The engines are expected to sign-extend the first 32-bits of 64-bit in as signed 32-bit int. func newOperationSignExtend64From32() unionOperation { return unionOperation{Kind: operationKindSignExtend64From32} } // NewOperationMemoryInit is a constructor for unionOperation with operationKindMemoryInit. // // This corresponds to wasm.OpcodeMemoryInitName. // // dataIndex is the index of the data instance in ModuleInstance.DataInstances // by which this operation instantiates a part of the memory. func newOperationMemoryInit(dataIndex uint32) unionOperation { return unionOperation{Kind: operationKindMemoryInit, U1: uint64(dataIndex)} } // NewOperationDataDrop implements Operation. // // This corresponds to wasm.OpcodeDataDropName. // // dataIndex is the index of the data instance in ModuleInstance.DataInstances // which this operation drops. func newOperationDataDrop(dataIndex uint32) unionOperation { return unionOperation{Kind: operationKindDataDrop, U1: uint64(dataIndex)} } // NewOperationMemoryCopy is a consuctor for unionOperation with operationKindMemoryCopy. // // This corresponds to wasm.OpcodeMemoryCopyName. func newOperationMemoryCopy() unionOperation { return unionOperation{Kind: operationKindMemoryCopy} } // NewOperationMemoryFill is a consuctor for unionOperation with operationKindMemoryFill. func newOperationMemoryFill() unionOperation { return unionOperation{Kind: operationKindMemoryFill} } // NewOperationTableInit is a constructor for unionOperation with operationKindTableInit. // // This corresponds to wasm.OpcodeTableInitName. // // elemIndex is the index of the element by which this operation initializes a part of the table. // tableIndex is the index of the table on which this operation initialize by the target element. func newOperationTableInit(elemIndex, tableIndex uint32) unionOperation { return unionOperation{Kind: operationKindTableInit, U1: uint64(elemIndex), U2: uint64(tableIndex)} } // NewOperationElemDrop is a constructor for unionOperation with operationKindElemDrop. // // This corresponds to wasm.OpcodeElemDropName. // // elemIndex is the index of the element which this operation drops. func newOperationElemDrop(elemIndex uint32) unionOperation { return unionOperation{Kind: operationKindElemDrop, U1: uint64(elemIndex)} } // NewOperationTableCopy implements Operation. // // This corresponds to wasm.OpcodeTableCopyName. func newOperationTableCopy(srcTableIndex, dstTableIndex uint32) unionOperation { return unionOperation{Kind: operationKindTableCopy, U1: uint64(srcTableIndex), U2: uint64(dstTableIndex)} } // NewOperationRefFunc constructor for unionOperation with operationKindRefFunc. // // This corresponds to wasm.OpcodeRefFuncName, and engines are expected to // push the opaque pointer value of engine specific func for the given FunctionIndex. // // Note: in wazero, we express any reference types (funcref or externref) as opaque pointers which is uint64. // Therefore, the engine implementations emit instructions to push the address of *function onto the stack. func newOperationRefFunc(functionIndex uint32) unionOperation { return unionOperation{Kind: operationKindRefFunc, U1: uint64(functionIndex)} } // NewOperationTableGet constructor for unionOperation with operationKindTableGet. // // This corresponds to wasm.OpcodeTableGetName. func newOperationTableGet(tableIndex uint32) unionOperation { return unionOperation{Kind: operationKindTableGet, U1: uint64(tableIndex)} } // NewOperationTableSet constructor for unionOperation with operationKindTableSet. // // This corresponds to wasm.OpcodeTableSetName. func newOperationTableSet(tableIndex uint32) unionOperation { return unionOperation{Kind: operationKindTableSet, U1: uint64(tableIndex)} } // NewOperationTableSize constructor for unionOperation with operationKindTableSize. // // This corresponds to wasm.OpcodeTableSizeName. func newOperationTableSize(tableIndex uint32) unionOperation { return unionOperation{Kind: operationKindTableSize, U1: uint64(tableIndex)} } // NewOperationTableGrow constructor for unionOperation with operationKindTableGrow. // // This corresponds to wasm.OpcodeTableGrowName. func newOperationTableGrow(tableIndex uint32) unionOperation { return unionOperation{Kind: operationKindTableGrow, U1: uint64(tableIndex)} } // NewOperationTableFill constructor for unionOperation with operationKindTableFill. // // This corresponds to wasm.OpcodeTableFillName. func newOperationTableFill(tableIndex uint32) unionOperation { return unionOperation{Kind: operationKindTableFill, U1: uint64(tableIndex)} } // NewOperationV128Const constructor for unionOperation with operationKindV128Const func newOperationV128Const(lo, hi uint64) unionOperation { return unionOperation{Kind: operationKindV128Const, U1: lo, U2: hi} } // shape corresponds to a shape of v128 values. // https://webassembly.github.io/spec/core/syntax/instructions.html#syntax-shape type shape = byte const ( shapeI8x16 shape = iota shapeI16x8 shapeI32x4 shapeI64x2 shapeF32x4 shapeF64x2 ) func shapeName(s shape) (ret string) { switch s { case shapeI8x16: ret = "I8x16" case shapeI16x8: ret = "I16x8" case shapeI32x4: ret = "I32x4" case shapeI64x2: ret = "I64x2" case shapeF32x4: ret = "F32x4" case shapeF64x2: ret = "F64x2" } return } // NewOperationV128Add constructor for unionOperation with operationKindV128Add. // // This corresponds to wasm.OpcodeVecI8x16AddName wasm.OpcodeVecI16x8AddName wasm.OpcodeVecI32x4AddName // // wasm.OpcodeVecI64x2AddName wasm.OpcodeVecF32x4AddName wasm.OpcodeVecF64x2AddName func newOperationV128Add(shape shape) unionOperation { return unionOperation{Kind: operationKindV128Add, B1: shape} } // NewOperationV128Sub constructor for unionOperation with operationKindV128Sub. // // This corresponds to wasm.OpcodeVecI8x16SubName wasm.OpcodeVecI16x8SubName wasm.OpcodeVecI32x4SubName // // wasm.OpcodeVecI64x2SubName wasm.OpcodeVecF32x4SubName wasm.OpcodeVecF64x2SubName func newOperationV128Sub(shape shape) unionOperation { return unionOperation{Kind: operationKindV128Sub, B1: shape} } // v128LoadType represents a type of wasm.OpcodeVecV128Load* instructions. type v128LoadType = byte const ( // v128LoadType128 corresponds to wasm.OpcodeVecV128LoadName. v128LoadType128 v128LoadType = iota // v128LoadType8x8s corresponds to wasm.OpcodeVecV128Load8x8SName. v128LoadType8x8s // v128LoadType8x8u corresponds to wasm.OpcodeVecV128Load8x8UName. v128LoadType8x8u // v128LoadType16x4s corresponds to wasm.OpcodeVecV128Load16x4SName v128LoadType16x4s // v128LoadType16x4u corresponds to wasm.OpcodeVecV128Load16x4UName v128LoadType16x4u // v128LoadType32x2s corresponds to wasm.OpcodeVecV128Load32x2SName v128LoadType32x2s // v128LoadType32x2u corresponds to wasm.OpcodeVecV128Load32x2UName v128LoadType32x2u // v128LoadType8Splat corresponds to wasm.OpcodeVecV128Load8SplatName v128LoadType8Splat // v128LoadType16Splat corresponds to wasm.OpcodeVecV128Load16SplatName v128LoadType16Splat // v128LoadType32Splat corresponds to wasm.OpcodeVecV128Load32SplatName v128LoadType32Splat // v128LoadType64Splat corresponds to wasm.OpcodeVecV128Load64SplatName v128LoadType64Splat // v128LoadType32zero corresponds to wasm.OpcodeVecV128Load32zeroName v128LoadType32zero // v128LoadType64zero corresponds to wasm.OpcodeVecV128Load64zeroName v128LoadType64zero ) // NewOperationV128Load is a constructor for unionOperation with operationKindV128Load. // // This corresponds to // // wasm.OpcodeVecV128LoadName wasm.OpcodeVecV128Load8x8SName wasm.OpcodeVecV128Load8x8UName // wasm.OpcodeVecV128Load16x4SName wasm.OpcodeVecV128Load16x4UName wasm.OpcodeVecV128Load32x2SName // wasm.OpcodeVecV128Load32x2UName wasm.OpcodeVecV128Load8SplatName wasm.OpcodeVecV128Load16SplatName // wasm.OpcodeVecV128Load32SplatName wasm.OpcodeVecV128Load64SplatName wasm.OpcodeVecV128Load32zeroName // wasm.OpcodeVecV128Load64zeroName func newOperationV128Load(loadType v128LoadType, arg memoryArg) unionOperation { return unionOperation{Kind: operationKindV128Load, B1: loadType, U1: uint64(arg.Alignment), U2: uint64(arg.Offset)} } // NewOperationV128LoadLane is a constructor for unionOperation with operationKindV128LoadLane. // // This corresponds to wasm.OpcodeVecV128Load8LaneName wasm.OpcodeVecV128Load16LaneName // // wasm.OpcodeVecV128Load32LaneName wasm.OpcodeVecV128Load64LaneName. // // laneIndex is >=0 && <(128/LaneSize). // laneSize is either 8, 16, 32, or 64. func newOperationV128LoadLane(laneIndex, laneSize byte, arg memoryArg) unionOperation { return unionOperation{Kind: operationKindV128LoadLane, B1: laneSize, B2: laneIndex, U1: uint64(arg.Alignment), U2: uint64(arg.Offset)} } // NewOperationV128Store is a constructor for unionOperation with operationKindV128Store. // // This corresponds to wasm.OpcodeVecV128Load8LaneName wasm.OpcodeVecV128Load16LaneName // // wasm.OpcodeVecV128Load32LaneName wasm.OpcodeVecV128Load64LaneName. func newOperationV128Store(arg memoryArg) unionOperation { return unionOperation{ Kind: operationKindV128Store, U1: uint64(arg.Alignment), U2: uint64(arg.Offset), } } // NewOperationV128StoreLane implements Operation. // // This corresponds to wasm.OpcodeVecV128Load8LaneName wasm.OpcodeVecV128Load16LaneName // // wasm.OpcodeVecV128Load32LaneName wasm.OpcodeVecV128Load64LaneName. // // laneIndex is >=0 && <(128/LaneSize). // laneSize is either 8, 16, 32, or 64. func newOperationV128StoreLane(laneIndex byte, laneSize byte, arg memoryArg) unionOperation { return unionOperation{ Kind: operationKindV128StoreLane, B1: laneSize, B2: laneIndex, U1: uint64(arg.Alignment), U2: uint64(arg.Offset), } } // NewOperationV128ExtractLane is a constructor for unionOperation with operationKindV128ExtractLane. // // This corresponds to // // wasm.OpcodeVecI8x16ExtractLaneSName wasm.OpcodeVecI8x16ExtractLaneUName // wasm.OpcodeVecI16x8ExtractLaneSName wasm.OpcodeVecI16x8ExtractLaneUName // wasm.OpcodeVecI32x4ExtractLaneName wasm.OpcodeVecI64x2ExtractLaneName // wasm.OpcodeVecF32x4ExtractLaneName wasm.OpcodeVecF64x2ExtractLaneName. // // laneIndex is >=0 && =0 &&