package interpreter
import (
"bytes"
"encoding/binary"
"fmt"
"math"
"strings"
"github.com/tetratelabs/wazero/api"
"github.com/tetratelabs/wazero/internal/leb128"
"github.com/tetratelabs/wazero/internal/wasm"
)
type controlFrameKind byte
const (
controlFrameKindBlockWithContinuationLabel controlFrameKind = iota
controlFrameKindBlockWithoutContinuationLabel
controlFrameKindFunction
controlFrameKindLoop
controlFrameKindIfWithElse
controlFrameKindIfWithoutElse
)
type (
controlFrame struct {
frameID uint32
originalStackLenWithoutParam int
originalStackLenWithoutParamUint64 int
blockType *wasm .FunctionType
kind controlFrameKind
}
controlFrames struct { frames []controlFrame }
)
func (c *controlFrame ) ensureContinuation () {
if c .kind == controlFrameKindBlockWithoutContinuationLabel {
c .kind = controlFrameKindBlockWithContinuationLabel
}
}
func (c *controlFrame ) asLabel () label {
switch c .kind {
case controlFrameKindBlockWithContinuationLabel ,
controlFrameKindBlockWithoutContinuationLabel :
return newLabel (labelKindContinuation , c .frameID )
case controlFrameKindLoop :
return newLabel (labelKindHeader , c .frameID )
case controlFrameKindFunction :
return newLabel (labelKindReturn , 0 )
case controlFrameKindIfWithElse ,
controlFrameKindIfWithoutElse :
return newLabel (labelKindContinuation , c .frameID )
}
panic (fmt .Sprintf ("unreachable: a bug in interpreterir implementation: %v" , c .kind ))
}
func (c *controlFrames ) functionFrame () *controlFrame {
return &c .frames [0 ]
}
func (c *controlFrames ) get (n int ) *controlFrame {
return &c .frames [len (c .frames )-n -1 ]
}
func (c *controlFrames ) top () *controlFrame {
return &c .frames [len (c .frames )-1 ]
}
func (c *controlFrames ) empty () bool {
return len (c .frames ) == 0
}
func (c *controlFrames ) pop () (frame *controlFrame ) {
frame = c .top ()
c .frames = c .frames [:len (c .frames )-1 ]
return
}
func (c *controlFrames ) push (frame controlFrame ) {
c .frames = append (c .frames , frame )
}
func (c *compiler ) initializeStack () {
c .localIndexToStackHeightInUint64 = c .localIndexToStackHeightInUint64 [:0 ]
var current int
for _ , lt := range c .sig .Params {
c .localIndexToStackHeightInUint64 = append (c .localIndexToStackHeightInUint64 , current )
if lt == wasm .ValueTypeV128 {
current ++
}
current ++
}
if c .callFrameStackSizeInUint64 > 0 {
if diff := c .sig .ResultNumInUint64 - c .sig .ParamNumInUint64 ; diff > 0 {
current += diff
}
}
current += c .callFrameStackSizeInUint64
for _ , lt := range c .localTypes {
c .localIndexToStackHeightInUint64 = append (c .localIndexToStackHeightInUint64 , current )
if lt == wasm .ValueTypeV128 {
current ++
}
current ++
}
for _ , t := range c .sig .Params {
c .stackPush (wasmValueTypeTounsignedType (t ))
}
if c .callFrameStackSizeInUint64 > 0 {
for i := 0 ; i < c .sig .ResultNumInUint64 -c .sig .ParamNumInUint64 ; i ++ {
c .stackPush (unsignedTypeI64 )
}
for i := 0 ; i < c .callFrameStackSizeInUint64 ; i ++ {
c .stackPush (unsignedTypeI64 )
}
}
}
type compiler struct {
module *wasm .Module
enabledFeatures api .CoreFeatures
callFrameStackSizeInUint64 int
stack []unsignedType
stackLenInUint64 int
currentFrameID uint32
controlFrames controlFrames
unreachableState struct {
on bool
depth int
}
pc, currentOpPC uint64
result compilationResult
body []byte
sig *wasm .FunctionType
localTypes []wasm .ValueType
localIndexToStackHeightInUint64 []int
types []wasm .FunctionType
funcs []uint32
globals []wasm .GlobalType
needSourceOffset bool
bodyOffsetInCodeSection uint64
ensureTermination bool
br *bytes .Reader
funcTypeToSigs funcTypeToIRSignatures
next int
}
func (c *compiler ) stackDump () string {
strs := make ([]string , 0 , len (c .stack ))
for _ , s := range c .stack {
strs = append (strs , s .String ())
}
return "[" + strings .Join (strs , ", " ) + "]"
}
func (c *compiler ) markUnreachable () {
c .unreachableState .on = true
}
func (c *compiler ) resetUnreachable () {
c .unreachableState .on = false
}
type memoryType byte
const (
memoryTypeNone memoryType = iota
memoryTypeStandard
memoryTypeShared
)
type compilationResult struct {
Operations []unionOperation
IROperationSourceOffsetsInWasmBinary []uint64
LabelCallers map [label ]uint32
UsesMemory bool
Globals []wasm .GlobalType
Functions []wasm .Index
Types []wasm .FunctionType
Memory memoryType
HasTable bool
HasDataInstances bool
HasElementInstances bool
}
func newCompiler(enabledFeatures api .CoreFeatures , callFrameStackSizeInUint64 int , module *wasm .Module , ensureTermination bool ) (*compiler , error ) {
functions , globals , mem , tables , err := module .AllDeclarations ()
if err != nil {
return nil , err
}
hasTable , hasDataInstances , hasElementInstances := len (tables ) > 0 ,
len (module .DataSection ) > 0 , len (module .ElementSection ) > 0
var mt memoryType
switch {
case mem == nil :
mt = memoryTypeNone
case mem .IsShared :
mt = memoryTypeShared
default :
mt = memoryTypeStandard
}
types := module .TypeSection
c := &compiler {
module : module ,
enabledFeatures : enabledFeatures ,
controlFrames : controlFrames {},
callFrameStackSizeInUint64 : callFrameStackSizeInUint64 ,
result : compilationResult {
Globals : globals ,
Functions : functions ,
Types : types ,
Memory : mt ,
HasTable : hasTable ,
HasDataInstances : hasDataInstances ,
HasElementInstances : hasElementInstances ,
LabelCallers : map [label ]uint32 {},
},
globals : globals ,
funcs : functions ,
types : types ,
ensureTermination : ensureTermination ,
br : bytes .NewReader (nil ),
funcTypeToSigs : funcTypeToIRSignatures {
indirectCalls : make ([]*signature , len (types )),
directCalls : make ([]*signature , len (types )),
wasmTypes : types ,
},
needSourceOffset : module .DWARFLines != nil ,
}
return c , nil
}
func (c *compiler ) Next () (*compilationResult , error ) {
funcIndex := c .next
code := &c .module .CodeSection [funcIndex ]
sig := &c .types [c .module .FunctionSection [funcIndex ]]
c .result .Operations = c .result .Operations [:0 ]
c .result .IROperationSourceOffsetsInWasmBinary = c .result .IROperationSourceOffsetsInWasmBinary [:0 ]
c .result .UsesMemory = false
for frameID := uint32 (0 ); frameID <= c .currentFrameID ; frameID ++ {
for k := labelKind (0 ); k < labelKindNum ; k ++ {
delete (c .result .LabelCallers , newLabel (k , frameID ))
}
}
c .pc = 0
c .currentOpPC = 0
c .currentFrameID = 0
c .stackLenInUint64 = 0
c .unreachableState .on , c .unreachableState .depth = false , 0
if err := c .compile (sig , code .Body , code .LocalTypes , code .BodyOffsetInCodeSection ); err != nil {
return nil , err
}
c .next ++
return &c .result , nil
}
func (c *compiler ) compile (sig *wasm .FunctionType , body []byte , localTypes []wasm .ValueType , bodyOffsetInCodeSection uint64 ) error {
c .body = body
c .localTypes = localTypes
c .sig = sig
c .bodyOffsetInCodeSection = bodyOffsetInCodeSection
c .stack = c .stack [:0 ]
c .controlFrames .frames = c .controlFrames .frames [:0 ]
c .initializeStack ()
for _ , t := range c .localTypes {
c .emitDefaultValue (t )
}
c .controlFrames .push (controlFrame {
frameID : c .nextFrameID (),
blockType : c .sig ,
kind : controlFrameKindFunction ,
})
for !c .controlFrames .empty () && c .pc < uint64 (len (c .body )) {
if err := c .handleInstruction (); err != nil {
return fmt .Errorf ("handling instruction: %w" , err )
}
}
return nil
}
func (c *compiler ) handleInstruction () error {
op := c .body [c .pc ]
c .currentOpPC = c .pc
if false {
var instName string
if op == wasm .OpcodeVecPrefix {
instName = wasm .VectorInstructionName (c .body [c .pc +1 ])
} else if op == wasm .OpcodeAtomicPrefix {
instName = wasm .AtomicInstructionName (c .body [c .pc +1 ])
} else if op == wasm .OpcodeMiscPrefix {
instName = wasm .MiscInstructionName (c .body [c .pc +1 ])
} else {
instName = wasm .InstructionName (op )
}
fmt .Printf ("handling %s, unreachable_state(on=%v,depth=%d), stack=%v\n" ,
instName , c .unreachableState .on , c .unreachableState .depth , c .stack ,
)
}
var peekValueType unsignedType
if len (c .stack ) > 0 {
peekValueType = c .stackPeek ()
}
index , err := c .applyToStack (op )
if err != nil {
return fmt .Errorf ("apply stack failed for %s: %w" , wasm .InstructionName (op ), err )
}
operatorSwitch :
switch op {
case wasm .OpcodeUnreachable :
c .emit (newOperationUnreachable ())
c .markUnreachable ()
case wasm .OpcodeNop :
case wasm .OpcodeBlock :
c .br .Reset (c .body [c .pc +1 :])
bt , num , err := wasm .DecodeBlockType (c .types , c .br , c .enabledFeatures )
if err != nil {
return fmt .Errorf ("reading block type for block instruction: %w" , err )
}
c .pc += num
if c .unreachableState .on {
c .unreachableState .depth ++
break operatorSwitch
}
frame := controlFrame {
frameID : c .nextFrameID (),
originalStackLenWithoutParam : len (c .stack ) - len (bt .Params ),
originalStackLenWithoutParamUint64 : c .stackLenInUint64 - bt .ParamNumInUint64 ,
kind : controlFrameKindBlockWithoutContinuationLabel ,
blockType : bt ,
}
c .controlFrames .push (frame )
case wasm .OpcodeLoop :
c .br .Reset (c .body [c .pc +1 :])
bt , num , err := wasm .DecodeBlockType (c .types , c .br , c .enabledFeatures )
if err != nil {
return fmt .Errorf ("reading block type for loop instruction: %w" , err )
}
c .pc += num
if c .unreachableState .on {
c .unreachableState .depth ++
break operatorSwitch
}
frame := controlFrame {
frameID : c .nextFrameID (),
originalStackLenWithoutParam : len (c .stack ) - len (bt .Params ),
originalStackLenWithoutParamUint64 : c .stackLenInUint64 - bt .ParamNumInUint64 ,
kind : controlFrameKindLoop ,
blockType : bt ,
}
c .controlFrames .push (frame )
loopLabel := newLabel (labelKindHeader , frame .frameID )
c .result .LabelCallers [loopLabel ]++
c .emit (newOperationBr (loopLabel ))
c .emit (newOperationLabel (loopLabel ))
if c .ensureTermination {
c .emit (newOperationBuiltinFunctionCheckExitCode ())
}
case wasm .OpcodeIf :
c .br .Reset (c .body [c .pc +1 :])
bt , num , err := wasm .DecodeBlockType (c .types , c .br , c .enabledFeatures )
if err != nil {
return fmt .Errorf ("reading block type for if instruction: %w" , err )
}
c .pc += num
if c .unreachableState .on {
c .unreachableState .depth ++
break operatorSwitch
}
frame := controlFrame {
frameID : c .nextFrameID (),
originalStackLenWithoutParam : len (c .stack ) - len (bt .Params ),
originalStackLenWithoutParamUint64 : c .stackLenInUint64 - bt .ParamNumInUint64 ,
kind : controlFrameKindIfWithoutElse ,
blockType : bt ,
}
c .controlFrames .push (frame )
thenLabel := newLabel (labelKindHeader , frame .frameID )
elseLabel := newLabel (labelKindElse , frame .frameID )
c .result .LabelCallers [thenLabel ]++
c .result .LabelCallers [elseLabel ]++
c .emit (newOperationBrIf (thenLabel , elseLabel , nopinclusiveRange ))
c .emit (newOperationLabel (thenLabel ))
case wasm .OpcodeElse :
frame := c .controlFrames .top ()
if c .unreachableState .on && c .unreachableState .depth > 0 {
break operatorSwitch
} else if c .unreachableState .on {
top := c .controlFrames .top ()
c .stackSwitchAt (top )
top .kind = controlFrameKindIfWithElse
for _ , t := range frame .blockType .Params {
c .stackPush (wasmValueTypeTounsignedType (t ))
}
elseLabel := newLabel (labelKindElse , frame .frameID )
c .resetUnreachable ()
c .emit (
newOperationLabel (elseLabel ),
)
break operatorSwitch
}
frame .kind = controlFrameKindIfWithElse
dropOp := newOperationDrop (c .getFrameDropRange (frame , false ))
c .stackSwitchAt (frame )
for _ , t := range frame .blockType .Params {
c .stackPush (wasmValueTypeTounsignedType (t ))
}
elseLabel := newLabel (labelKindElse , frame .frameID )
continuationLabel := newLabel (labelKindContinuation , frame .frameID )
c .result .LabelCallers [continuationLabel ]++
c .emit (dropOp )
c .emit (newOperationBr (continuationLabel ))
c .emit (newOperationLabel (elseLabel ))
case wasm .OpcodeEnd :
if c .unreachableState .on && c .unreachableState .depth > 0 {
c .unreachableState .depth --
break operatorSwitch
} else if c .unreachableState .on {
c .resetUnreachable ()
frame := c .controlFrames .pop ()
if c .controlFrames .empty () {
return nil
}
c .stackSwitchAt (frame )
for _ , t := range frame .blockType .Results {
c .stackPush (wasmValueTypeTounsignedType (t ))
}
continuationLabel := newLabel (labelKindContinuation , frame .frameID )
if frame .kind == controlFrameKindIfWithoutElse {
elseLabel := newLabel (labelKindElse , frame .frameID )
c .result .LabelCallers [continuationLabel ]++
c .emit (newOperationLabel (elseLabel ))
c .emit (newOperationBr (continuationLabel ))
c .emit (newOperationLabel (continuationLabel ))
} else {
c .emit (
newOperationLabel (continuationLabel ),
)
}
break operatorSwitch
}
frame := c .controlFrames .pop ()
dropOp := newOperationDrop (c .getFrameDropRange (frame , true ))
c .stackSwitchAt (frame )
for _ , t := range frame .blockType .Results {
c .stackPush (wasmValueTypeTounsignedType (t ))
}
switch frame .kind {
case controlFrameKindFunction :
if !c .controlFrames .empty () {
panic ("bug: found more function control frames" )
}
c .emit (dropOp )
c .emit (newOperationBr (newLabel (labelKindReturn , 0 )))
case controlFrameKindIfWithoutElse :
elseLabel := newLabel (labelKindElse , frame .frameID )
continuationLabel := newLabel (labelKindContinuation , frame .frameID )
c .result .LabelCallers [continuationLabel ] += 2
c .emit (dropOp )
c .emit (newOperationBr (continuationLabel ))
c .emit (newOperationLabel (elseLabel ))
c .emit (newOperationBr (continuationLabel ))
c .emit (newOperationLabel (continuationLabel ))
case controlFrameKindBlockWithContinuationLabel ,
controlFrameKindIfWithElse :
continuationLabel := newLabel (labelKindContinuation , frame .frameID )
c .result .LabelCallers [continuationLabel ]++
c .emit (dropOp )
c .emit (newOperationBr (continuationLabel ))
c .emit (newOperationLabel (continuationLabel ))
case controlFrameKindLoop , controlFrameKindBlockWithoutContinuationLabel :
c .emit (
dropOp ,
)
default :
panic (fmt .Errorf ("bug: invalid control frame Kind: 0x%x" , frame .kind ))
}
case wasm .OpcodeBr :
targetIndex , n , err := leb128 .LoadUint32 (c .body [c .pc +1 :])
if err != nil {
return fmt .Errorf ("read the target for br_if: %w" , err )
}
c .pc += n
if c .unreachableState .on {
break operatorSwitch
}
targetFrame := c .controlFrames .get (int (targetIndex ))
targetFrame .ensureContinuation ()
dropOp := newOperationDrop (c .getFrameDropRange (targetFrame , false ))
targetID := targetFrame .asLabel ()
c .result .LabelCallers [targetID ]++
c .emit (dropOp )
c .emit (newOperationBr (targetID ))
c .markUnreachable ()
case wasm .OpcodeBrIf :
targetIndex , n , err := leb128 .LoadUint32 (c .body [c .pc +1 :])
if err != nil {
return fmt .Errorf ("read the target for br_if: %w" , err )
}
c .pc += n
if c .unreachableState .on {
break operatorSwitch
}
targetFrame := c .controlFrames .get (int (targetIndex ))
targetFrame .ensureContinuation ()
drop := c .getFrameDropRange (targetFrame , false )
target := targetFrame .asLabel ()
c .result .LabelCallers [target ]++
continuationLabel := newLabel (labelKindHeader , c .nextFrameID ())
c .result .LabelCallers [continuationLabel ]++
c .emit (newOperationBrIf (target , continuationLabel , drop ))
c .emit (newOperationLabel (continuationLabel ))
case wasm .OpcodeBrTable :
c .br .Reset (c .body [c .pc +1 :])
r := c .br
numTargets , n , err := leb128 .DecodeUint32 (r )
if err != nil {
return fmt .Errorf ("error reading number of targets in br_table: %w" , err )
}
c .pc += n
if c .unreachableState .on {
for i := uint32 (0 ); i <= numTargets ; i ++ {
_ , n , err := leb128 .DecodeUint32 (r )
if err != nil {
return fmt .Errorf ("error reading target %d in br_table: %w" , i , err )
}
c .pc += n
}
break operatorSwitch
}
s := numTargets * 2
targetLabels := make ([]uint64 , 2 +s )
for i := uint32 (0 ); i < s ; i += 2 {
l , n , err := leb128 .DecodeUint32 (r )
if err != nil {
return fmt .Errorf ("error reading target %d in br_table: %w" , i , err )
}
c .pc += n
targetFrame := c .controlFrames .get (int (l ))
targetFrame .ensureContinuation ()
drop := c .getFrameDropRange (targetFrame , false )
targetLabel := targetFrame .asLabel ()
targetLabels [i ] = uint64 (targetLabel )
targetLabels [i +1 ] = drop .AsU64 ()
c .result .LabelCallers [targetLabel ]++
}
l , n , err := leb128 .DecodeUint32 (r )
if err != nil {
return fmt .Errorf ("error reading default target of br_table: %w" , err )
}
c .pc += n
defaultTargetFrame := c .controlFrames .get (int (l ))
defaultTargetFrame .ensureContinuation ()
defaultTargetDrop := c .getFrameDropRange (defaultTargetFrame , false )
defaultLabel := defaultTargetFrame .asLabel ()
c .result .LabelCallers [defaultLabel ]++
targetLabels [s ] = uint64 (defaultLabel )
targetLabels [s +1 ] = defaultTargetDrop .AsU64 ()
c .emit (newOperationBrTable (targetLabels ))
c .markUnreachable ()
case wasm .OpcodeReturn :
functionFrame := c .controlFrames .functionFrame ()
dropOp := newOperationDrop (c .getFrameDropRange (functionFrame , false ))
c .emit (dropOp )
c .emit (newOperationBr (functionFrame .asLabel ()))
c .markUnreachable ()
case wasm .OpcodeCall :
c .emit (
newOperationCall (index ),
)
case wasm .OpcodeCallIndirect :
typeIndex := index
tableIndex , n , err := leb128 .LoadUint32 (c .body [c .pc +1 :])
if err != nil {
return fmt .Errorf ("read target for br_table: %w" , err )
}
c .pc += n
c .emit (
newOperationCallIndirect (typeIndex , tableIndex ),
)
case wasm .OpcodeDrop :
r := inclusiveRange {Start : 0 , End : 0 }
if peekValueType == unsignedTypeV128 {
r .End ++
}
c .emit (newOperationDrop (r ))
case wasm .OpcodeSelect :
if c .unreachableState .on {
break operatorSwitch
}
isTargetVector := c .stackPeek () == unsignedTypeV128
c .emit (
newOperationSelect (isTargetVector ),
)
case wasm .OpcodeTypedSelect :
c .pc += 2
if c .unreachableState .on {
break operatorSwitch
}
isTargetVector := c .stackPeek () == unsignedTypeV128
c .emit (
newOperationSelect (isTargetVector ),
)
case wasm .OpcodeLocalGet :
depth := c .localDepth (index )
if isVector := c .localType (index ) == wasm .ValueTypeV128 ; !isVector {
c .emit (
newOperationPick (depth -1 , isVector ),
)
} else {
c .emit (
newOperationPick (depth -2 , isVector ),
)
}
case wasm .OpcodeLocalSet :
depth := c .localDepth (index )
isVector := c .localType (index ) == wasm .ValueTypeV128
if isVector {
c .emit (
newOperationSet (depth +2 , isVector ),
)
} else {
c .emit (
newOperationSet (depth +1 , isVector ),
)
}
case wasm .OpcodeLocalTee :
depth := c .localDepth (index )
isVector := c .localType (index ) == wasm .ValueTypeV128
if isVector {
c .emit (newOperationPick (1 , isVector ))
c .emit (newOperationSet (depth +2 , isVector ))
} else {
c .emit (
newOperationPick (0 , isVector ))
c .emit (newOperationSet (depth +1 , isVector ))
}
case wasm .OpcodeGlobalGet :
c .emit (
newOperationGlobalGet (index ),
)
case wasm .OpcodeGlobalSet :
c .emit (
newOperationGlobalSet (index ),
)
case wasm .OpcodeI32Load :
imm , err := c .readMemoryArg (wasm .OpcodeI32LoadName )
if err != nil {
return err
}
c .emit (newOperationLoad (unsignedTypeI32 , imm ))
case wasm .OpcodeI64Load :
imm , err := c .readMemoryArg (wasm .OpcodeI64LoadName )
if err != nil {
return err
}
c .emit (newOperationLoad (unsignedTypeI64 , imm ))
case wasm .OpcodeF32Load :
imm , err := c .readMemoryArg (wasm .OpcodeF32LoadName )
if err != nil {
return err
}
c .emit (newOperationLoad (unsignedTypeF32 , imm ))
case wasm .OpcodeF64Load :
imm , err := c .readMemoryArg (wasm .OpcodeF64LoadName )
if err != nil {
return err
}
c .emit (newOperationLoad (unsignedTypeF64 , imm ))
case wasm .OpcodeI32Load8S :
imm , err := c .readMemoryArg (wasm .OpcodeI32Load8SName )
if err != nil {
return err
}
c .emit (newOperationLoad8 (signedInt32 , imm ))
case wasm .OpcodeI32Load8U :
imm , err := c .readMemoryArg (wasm .OpcodeI32Load8UName )
if err != nil {
return err
}
c .emit (newOperationLoad8 (signedUint32 , imm ))
case wasm .OpcodeI32Load16S :
imm , err := c .readMemoryArg (wasm .OpcodeI32Load16SName )
if err != nil {
return err
}
c .emit (newOperationLoad16 (signedInt32 , imm ))
case wasm .OpcodeI32Load16U :
imm , err := c .readMemoryArg (wasm .OpcodeI32Load16UName )
if err != nil {
return err
}
c .emit (newOperationLoad16 (signedUint32 , imm ))
case wasm .OpcodeI64Load8S :
imm , err := c .readMemoryArg (wasm .OpcodeI64Load8SName )
if err != nil {
return err
}
c .emit (newOperationLoad8 (signedInt64 , imm ))
case wasm .OpcodeI64Load8U :
imm , err := c .readMemoryArg (wasm .OpcodeI64Load8UName )
if err != nil {
return err
}
c .emit (newOperationLoad8 (signedUint64 , imm ))
case wasm .OpcodeI64Load16S :
imm , err := c .readMemoryArg (wasm .OpcodeI64Load16SName )
if err != nil {
return err
}
c .emit (newOperationLoad16 (signedInt64 , imm ))
case wasm .OpcodeI64Load16U :
imm , err := c .readMemoryArg (wasm .OpcodeI64Load16UName )
if err != nil {
return err
}
c .emit (newOperationLoad16 (signedUint64 , imm ))
case wasm .OpcodeI64Load32S :
imm , err := c .readMemoryArg (wasm .OpcodeI64Load32SName )
if err != nil {
return err
}
c .emit (newOperationLoad32 (true , imm ))
case wasm .OpcodeI64Load32U :
imm , err := c .readMemoryArg (wasm .OpcodeI64Load32UName )
if err != nil {
return err
}
c .emit (newOperationLoad32 (false , imm ))
case wasm .OpcodeI32Store :
imm , err := c .readMemoryArg (wasm .OpcodeI32StoreName )
if err != nil {
return err
}
c .emit (
newOperationStore (unsignedTypeI32 , imm ),
)
case wasm .OpcodeI64Store :
imm , err := c .readMemoryArg (wasm .OpcodeI64StoreName )
if err != nil {
return err
}
c .emit (
newOperationStore (unsignedTypeI64 , imm ),
)
case wasm .OpcodeF32Store :
imm , err := c .readMemoryArg (wasm .OpcodeF32StoreName )
if err != nil {
return err
}
c .emit (
newOperationStore (unsignedTypeF32 , imm ),
)
case wasm .OpcodeF64Store :
imm , err := c .readMemoryArg (wasm .OpcodeF64StoreName )
if err != nil {
return err
}
c .emit (
newOperationStore (unsignedTypeF64 , imm ),
)
case wasm .OpcodeI32Store8 :
imm , err := c .readMemoryArg (wasm .OpcodeI32Store8Name )
if err != nil {
return err
}
c .emit (
newOperationStore8 (imm ),
)
case wasm .OpcodeI32Store16 :
imm , err := c .readMemoryArg (wasm .OpcodeI32Store16Name )
if err != nil {
return err
}
c .emit (
newOperationStore16 (imm ),
)
case wasm .OpcodeI64Store8 :
imm , err := c .readMemoryArg (wasm .OpcodeI64Store8Name )
if err != nil {
return err
}
c .emit (
newOperationStore8 (imm ),
)
case wasm .OpcodeI64Store16 :
imm , err := c .readMemoryArg (wasm .OpcodeI64Store16Name )
if err != nil {
return err
}
c .emit (
newOperationStore16 (imm ),
)
case wasm .OpcodeI64Store32 :
imm , err := c .readMemoryArg (wasm .OpcodeI64Store32Name )
if err != nil {
return err
}
c .emit (
newOperationStore32 (imm ),
)
case wasm .OpcodeMemorySize :
c .result .UsesMemory = true
c .pc ++
c .emit (
newOperationMemorySize (),
)
case wasm .OpcodeMemoryGrow :
c .result .UsesMemory = true
c .pc ++
c .emit (
newOperationMemoryGrow (),
)
case wasm .OpcodeI32Const :
val , num , err := leb128 .LoadInt32 (c .body [c .pc +1 :])
if err != nil {
return fmt .Errorf ("reading i32.const value: %v" , err )
}
c .pc += num
c .emit (
newOperationConstI32 (uint32 (val )),
)
case wasm .OpcodeI64Const :
val , num , err := leb128 .LoadInt64 (c .body [c .pc +1 :])
if err != nil {
return fmt .Errorf ("reading i64.const value: %v" , err )
}
c .pc += num
c .emit (
newOperationConstI64 (uint64 (val )),
)
case wasm .OpcodeF32Const :
v := math .Float32frombits (binary .LittleEndian .Uint32 (c .body [c .pc +1 :]))
c .pc += 4
c .emit (
newOperationConstF32 (v ),
)
case wasm .OpcodeF64Const :
v := math .Float64frombits (binary .LittleEndian .Uint64 (c .body [c .pc +1 :]))
c .pc += 8
c .emit (
newOperationConstF64 (v ),
)
case wasm .OpcodeI32Eqz :
c .emit (
newOperationEqz (unsignedInt32 ),
)
case wasm .OpcodeI32Eq :
c .emit (
newOperationEq (unsignedTypeI32 ),
)
case wasm .OpcodeI32Ne :
c .emit (
newOperationNe (unsignedTypeI32 ),
)
case wasm .OpcodeI32LtS :
c .emit (
newOperationLt (signedTypeInt32 ),
)
case wasm .OpcodeI32LtU :
c .emit (
newOperationLt (signedTypeUint32 ),
)
case wasm .OpcodeI32GtS :
c .emit (
newOperationGt (signedTypeInt32 ),
)
case wasm .OpcodeI32GtU :
c .emit (
newOperationGt (signedTypeUint32 ),
)
case wasm .OpcodeI32LeS :
c .emit (
newOperationLe (signedTypeInt32 ),
)
case wasm .OpcodeI32LeU :
c .emit (
newOperationLe (signedTypeUint32 ),
)
case wasm .OpcodeI32GeS :
c .emit (
newOperationGe (signedTypeInt32 ),
)
case wasm .OpcodeI32GeU :
c .emit (
newOperationGe (signedTypeUint32 ),
)
case wasm .OpcodeI64Eqz :
c .emit (
newOperationEqz (unsignedInt64 ),
)
case wasm .OpcodeI64Eq :
c .emit (
newOperationEq (unsignedTypeI64 ),
)
case wasm .OpcodeI64Ne :
c .emit (
newOperationNe (unsignedTypeI64 ),
)
case wasm .OpcodeI64LtS :
c .emit (
newOperationLt (signedTypeInt64 ),
)
case wasm .OpcodeI64LtU :
c .emit (
newOperationLt (signedTypeUint64 ),
)
case wasm .OpcodeI64GtS :
c .emit (
newOperationGt (signedTypeInt64 ),
)
case wasm .OpcodeI64GtU :
c .emit (
newOperationGt (signedTypeUint64 ),
)
case wasm .OpcodeI64LeS :
c .emit (
newOperationLe (signedTypeInt64 ),
)
case wasm .OpcodeI64LeU :
c .emit (
newOperationLe (signedTypeUint64 ),
)
case wasm .OpcodeI64GeS :
c .emit (
newOperationGe (signedTypeInt64 ),
)
case wasm .OpcodeI64GeU :
c .emit (
newOperationGe (signedTypeUint64 ),
)
case wasm .OpcodeF32Eq :
c .emit (
newOperationEq (unsignedTypeF32 ),
)
case wasm .OpcodeF32Ne :
c .emit (
newOperationNe (unsignedTypeF32 ),
)
case wasm .OpcodeF32Lt :
c .emit (
newOperationLt (signedTypeFloat32 ),
)
case wasm .OpcodeF32Gt :
c .emit (
newOperationGt (signedTypeFloat32 ),
)
case wasm .OpcodeF32Le :
c .emit (
newOperationLe (signedTypeFloat32 ),
)
case wasm .OpcodeF32Ge :
c .emit (
newOperationGe (signedTypeFloat32 ),
)
case wasm .OpcodeF64Eq :
c .emit (
newOperationEq (unsignedTypeF64 ),
)
case wasm .OpcodeF64Ne :
c .emit (
newOperationNe (unsignedTypeF64 ),
)
case wasm .OpcodeF64Lt :
c .emit (
newOperationLt (signedTypeFloat64 ),
)
case wasm .OpcodeF64Gt :
c .emit (
newOperationGt (signedTypeFloat64 ),
)
case wasm .OpcodeF64Le :
c .emit (
newOperationLe (signedTypeFloat64 ),
)
case wasm .OpcodeF64Ge :
c .emit (
newOperationGe (signedTypeFloat64 ),
)
case wasm .OpcodeI32Clz :
c .emit (
newOperationClz (unsignedInt32 ),
)
case wasm .OpcodeI32Ctz :
c .emit (
newOperationCtz (unsignedInt32 ),
)
case wasm .OpcodeI32Popcnt :
c .emit (
newOperationPopcnt (unsignedInt32 ),
)
case wasm .OpcodeI32Add :
c .emit (
newOperationAdd (unsignedTypeI32 ),
)
case wasm .OpcodeI32Sub :
c .emit (
newOperationSub (unsignedTypeI32 ),
)
case wasm .OpcodeI32Mul :
c .emit (
newOperationMul (unsignedTypeI32 ),
)
case wasm .OpcodeI32DivS :
c .emit (
newOperationDiv (signedTypeInt32 ),
)
case wasm .OpcodeI32DivU :
c .emit (
newOperationDiv (signedTypeUint32 ),
)
case wasm .OpcodeI32RemS :
c .emit (
newOperationRem (signedInt32 ),
)
case wasm .OpcodeI32RemU :
c .emit (
newOperationRem (signedUint32 ),
)
case wasm .OpcodeI32And :
c .emit (
newOperationAnd (unsignedInt32 ),
)
case wasm .OpcodeI32Or :
c .emit (
newOperationOr (unsignedInt32 ),
)
case wasm .OpcodeI32Xor :
c .emit (
newOperationXor (unsignedInt64 ),
)
case wasm .OpcodeI32Shl :
c .emit (
newOperationShl (unsignedInt32 ),
)
case wasm .OpcodeI32ShrS :
c .emit (
newOperationShr (signedInt32 ),
)
case wasm .OpcodeI32ShrU :
c .emit (
newOperationShr (signedUint32 ),
)
case wasm .OpcodeI32Rotl :
c .emit (
newOperationRotl (unsignedInt32 ),
)
case wasm .OpcodeI32Rotr :
c .emit (
newOperationRotr (unsignedInt32 ),
)
case wasm .OpcodeI64Clz :
c .emit (
newOperationClz (unsignedInt64 ),
)
case wasm .OpcodeI64Ctz :
c .emit (
newOperationCtz (unsignedInt64 ),
)
case wasm .OpcodeI64Popcnt :
c .emit (
newOperationPopcnt (unsignedInt64 ),
)
case wasm .OpcodeI64Add :
c .emit (
newOperationAdd (unsignedTypeI64 ),
)
case wasm .OpcodeI64Sub :
c .emit (
newOperationSub (unsignedTypeI64 ),
)
case wasm .OpcodeI64Mul :
c .emit (
newOperationMul (unsignedTypeI64 ),
)
case wasm .OpcodeI64DivS :
c .emit (
newOperationDiv (signedTypeInt64 ),
)
case wasm .OpcodeI64DivU :
c .emit (
newOperationDiv (signedTypeUint64 ),
)
case wasm .OpcodeI64RemS :
c .emit (
newOperationRem (signedInt64 ),
)
case wasm .OpcodeI64RemU :
c .emit (
newOperationRem (signedUint64 ),
)
case wasm .OpcodeI64And :
c .emit (
newOperationAnd (unsignedInt64 ),
)
case wasm .OpcodeI64Or :
c .emit (
newOperationOr (unsignedInt64 ),
)
case wasm .OpcodeI64Xor :
c .emit (
newOperationXor (unsignedInt64 ),
)
case wasm .OpcodeI64Shl :
c .emit (
newOperationShl (unsignedInt64 ),
)
case wasm .OpcodeI64ShrS :
c .emit (
newOperationShr (signedInt64 ),
)
case wasm .OpcodeI64ShrU :
c .emit (
newOperationShr (signedUint64 ),
)
case wasm .OpcodeI64Rotl :
c .emit (
newOperationRotl (unsignedInt64 ),
)
case wasm .OpcodeI64Rotr :
c .emit (
newOperationRotr (unsignedInt64 ),
)
case wasm .OpcodeF32Abs :
c .emit (
newOperationAbs (f32 ),
)
case wasm .OpcodeF32Neg :
c .emit (
newOperationNeg (f32 ),
)
case wasm .OpcodeF32Ceil :
c .emit (
newOperationCeil (f32 ),
)
case wasm .OpcodeF32Floor :
c .emit (
newOperationFloor (f32 ),
)
case wasm .OpcodeF32Trunc :
c .emit (
newOperationTrunc (f32 ),
)
case wasm .OpcodeF32Nearest :
c .emit (
newOperationNearest (f32 ),
)
case wasm .OpcodeF32Sqrt :
c .emit (
newOperationSqrt (f32 ),
)
case wasm .OpcodeF32Add :
c .emit (
newOperationAdd (unsignedTypeF32 ),
)
case wasm .OpcodeF32Sub :
c .emit (
newOperationSub (unsignedTypeF32 ),
)
case wasm .OpcodeF32Mul :
c .emit (
newOperationMul (unsignedTypeF32 ),
)
case wasm .OpcodeF32Div :
c .emit (
newOperationDiv (signedTypeFloat32 ),
)
case wasm .OpcodeF32Min :
c .emit (
newOperationMin (f32 ),
)
case wasm .OpcodeF32Max :
c .emit (
newOperationMax (f32 ),
)
case wasm .OpcodeF32Copysign :
c .emit (
newOperationCopysign (f32 ),
)
case wasm .OpcodeF64Abs :
c .emit (
newOperationAbs (f64 ),
)
case wasm .OpcodeF64Neg :
c .emit (
newOperationNeg (f64 ),
)
case wasm .OpcodeF64Ceil :
c .emit (
newOperationCeil (f64 ),
)
case wasm .OpcodeF64Floor :
c .emit (
newOperationFloor (f64 ),
)
case wasm .OpcodeF64Trunc :
c .emit (
newOperationTrunc (f64 ),
)
case wasm .OpcodeF64Nearest :
c .emit (
newOperationNearest (f64 ),
)
case wasm .OpcodeF64Sqrt :
c .emit (
newOperationSqrt (f64 ),
)
case wasm .OpcodeF64Add :
c .emit (
newOperationAdd (unsignedTypeF64 ),
)
case wasm .OpcodeF64Sub :
c .emit (
newOperationSub (unsignedTypeF64 ),
)
case wasm .OpcodeF64Mul :
c .emit (
newOperationMul (unsignedTypeF64 ),
)
case wasm .OpcodeF64Div :
c .emit (
newOperationDiv (signedTypeFloat64 ),
)
case wasm .OpcodeF64Min :
c .emit (
newOperationMin (f64 ),
)
case wasm .OpcodeF64Max :
c .emit (
newOperationMax (f64 ),
)
case wasm .OpcodeF64Copysign :
c .emit (
newOperationCopysign (f64 ),
)
case wasm .OpcodeI32WrapI64 :
c .emit (
newOperationI32WrapFromI64 (),
)
case wasm .OpcodeI32TruncF32S :
c .emit (
newOperationITruncFromF (f32 , signedInt32 , false ),
)
case wasm .OpcodeI32TruncF32U :
c .emit (
newOperationITruncFromF (f32 , signedUint32 , false ),
)
case wasm .OpcodeI32TruncF64S :
c .emit (
newOperationITruncFromF (f64 , signedInt32 , false ),
)
case wasm .OpcodeI32TruncF64U :
c .emit (
newOperationITruncFromF (f64 , signedUint32 , false ),
)
case wasm .OpcodeI64ExtendI32S :
c .emit (
newOperationExtend (true ),
)
case wasm .OpcodeI64ExtendI32U :
c .emit (
newOperationExtend (false ),
)
case wasm .OpcodeI64TruncF32S :
c .emit (
newOperationITruncFromF (f32 , signedInt64 , false ),
)
case wasm .OpcodeI64TruncF32U :
c .emit (
newOperationITruncFromF (f32 , signedUint64 , false ),
)
case wasm .OpcodeI64TruncF64S :
c .emit (
newOperationITruncFromF (f64 , signedInt64 , false ),
)
case wasm .OpcodeI64TruncF64U :
c .emit (
newOperationITruncFromF (f64 , signedUint64 , false ),
)
case wasm .OpcodeF32ConvertI32S :
c .emit (
newOperationFConvertFromI (signedInt32 , f32 ),
)
case wasm .OpcodeF32ConvertI32U :
c .emit (
newOperationFConvertFromI (signedUint32 , f32 ),
)
case wasm .OpcodeF32ConvertI64S :
c .emit (
newOperationFConvertFromI (signedInt64 , f32 ),
)
case wasm .OpcodeF32ConvertI64U :
c .emit (
newOperationFConvertFromI (signedUint64 , f32 ),
)
case wasm .OpcodeF32DemoteF64 :
c .emit (
newOperationF32DemoteFromF64 (),
)
case wasm .OpcodeF64ConvertI32S :
c .emit (
newOperationFConvertFromI (signedInt32 , f64 ),
)
case wasm .OpcodeF64ConvertI32U :
c .emit (
newOperationFConvertFromI (signedUint32 , f64 ),
)
case wasm .OpcodeF64ConvertI64S :
c .emit (
newOperationFConvertFromI (signedInt64 , f64 ),
)
case wasm .OpcodeF64ConvertI64U :
c .emit (
newOperationFConvertFromI (signedUint64 , f64 ),
)
case wasm .OpcodeF64PromoteF32 :
c .emit (
newOperationF64PromoteFromF32 (),
)
case wasm .OpcodeI32ReinterpretF32 :
c .emit (
newOperationI32ReinterpretFromF32 (),
)
case wasm .OpcodeI64ReinterpretF64 :
c .emit (
newOperationI64ReinterpretFromF64 (),
)
case wasm .OpcodeF32ReinterpretI32 :
c .emit (
newOperationF32ReinterpretFromI32 (),
)
case wasm .OpcodeF64ReinterpretI64 :
c .emit (
newOperationF64ReinterpretFromI64 (),
)
case wasm .OpcodeI32Extend8S :
c .emit (
newOperationSignExtend32From8 (),
)
case wasm .OpcodeI32Extend16S :
c .emit (
newOperationSignExtend32From16 (),
)
case wasm .OpcodeI64Extend8S :
c .emit (
newOperationSignExtend64From8 (),
)
case wasm .OpcodeI64Extend16S :
c .emit (
newOperationSignExtend64From16 (),
)
case wasm .OpcodeI64Extend32S :
c .emit (
newOperationSignExtend64From32 (),
)
case wasm .OpcodeRefFunc :
c .pc ++
index , num , err := leb128 .LoadUint32 (c .body [c .pc :])
if err != nil {
return fmt .Errorf ("failed to read function index for ref.func: %v" , err )
}
c .pc += num - 1
c .emit (
newOperationRefFunc (index ),
)
case wasm .OpcodeRefNull :
c .pc ++
c .emit (
newOperationConstI64 (0 ),
)
case wasm .OpcodeRefIsNull :
c .emit (
newOperationEqz (unsignedInt64 ),
)
case wasm .OpcodeTableGet :
c .pc ++
tableIndex , num , err := leb128 .LoadUint32 (c .body [c .pc :])
if err != nil {
return fmt .Errorf ("failed to read function index for table.get: %v" , err )
}
c .pc += num - 1
c .emit (
newOperationTableGet (tableIndex ),
)
case wasm .OpcodeTableSet :
c .pc ++
tableIndex , num , err := leb128 .LoadUint32 (c .body [c .pc :])
if err != nil {
return fmt .Errorf ("failed to read function index for table.set: %v" , err )
}
c .pc += num - 1
c .emit (
newOperationTableSet (tableIndex ),
)
case wasm .OpcodeMiscPrefix :
c .pc ++
miscOp , num , err := leb128 .LoadUint32 (c .body [c .pc :])
if err != nil {
return fmt .Errorf ("failed to read misc opcode: %v" , err )
}
c .pc += num - 1
switch byte (miscOp ) {
case wasm .OpcodeMiscI32TruncSatF32S :
c .emit (
newOperationITruncFromF (f32 , signedInt32 , true ),
)
case wasm .OpcodeMiscI32TruncSatF32U :
c .emit (
newOperationITruncFromF (f32 , signedUint32 , true ),
)
case wasm .OpcodeMiscI32TruncSatF64S :
c .emit (
newOperationITruncFromF (f64 , signedInt32 , true ),
)
case wasm .OpcodeMiscI32TruncSatF64U :
c .emit (
newOperationITruncFromF (f64 , signedUint32 , true ),
)
case wasm .OpcodeMiscI64TruncSatF32S :
c .emit (
newOperationITruncFromF (f32 , signedInt64 , true ),
)
case wasm .OpcodeMiscI64TruncSatF32U :
c .emit (
newOperationITruncFromF (f32 , signedUint64 , true ),
)
case wasm .OpcodeMiscI64TruncSatF64S :
c .emit (
newOperationITruncFromF (f64 , signedInt64 , true ),
)
case wasm .OpcodeMiscI64TruncSatF64U :
c .emit (
newOperationITruncFromF (f64 , signedUint64 , true ),
)
case wasm .OpcodeMiscMemoryInit :
c .result .UsesMemory = true
dataIndex , num , err := leb128 .LoadUint32 (c .body [c .pc +1 :])
if err != nil {
return fmt .Errorf ("reading i32.const value: %v" , err )
}
c .pc += num + 1
c .emit (
newOperationMemoryInit (dataIndex ),
)
case wasm .OpcodeMiscDataDrop :
dataIndex , num , err := leb128 .LoadUint32 (c .body [c .pc +1 :])
if err != nil {
return fmt .Errorf ("reading i32.const value: %v" , err )
}
c .pc += num
c .emit (
newOperationDataDrop (dataIndex ),
)
case wasm .OpcodeMiscMemoryCopy :
c .result .UsesMemory = true
c .pc += 2
c .emit (
newOperationMemoryCopy (),
)
case wasm .OpcodeMiscMemoryFill :
c .result .UsesMemory = true
c .pc += 1
c .emit (
newOperationMemoryFill (),
)
case wasm .OpcodeMiscTableInit :
elemIndex , num , err := leb128 .LoadUint32 (c .body [c .pc +1 :])
if err != nil {
return fmt .Errorf ("reading i32.const value: %v" , err )
}
c .pc += num
tableIndex , num , err := leb128 .LoadUint32 (c .body [c .pc +1 :])
if err != nil {
return fmt .Errorf ("reading i32.const value: %v" , err )
}
c .pc += num
c .emit (
newOperationTableInit (elemIndex , tableIndex ),
)
case wasm .OpcodeMiscElemDrop :
elemIndex , num , err := leb128 .LoadUint32 (c .body [c .pc +1 :])
if err != nil {
return fmt .Errorf ("reading i32.const value: %v" , err )
}
c .pc += num
c .emit (
newOperationElemDrop (elemIndex ),
)
case wasm .OpcodeMiscTableCopy :
dst , num , err := leb128 .LoadUint32 (c .body [c .pc +1 :])
if err != nil {
return fmt .Errorf ("reading i32.const value: %v" , err )
}
c .pc += num
src , num , err := leb128 .LoadUint32 (c .body [c .pc +1 :])
if err != nil {
return fmt .Errorf ("reading i32.const value: %v" , err )
}
c .pc += num
c .emit (
newOperationTableCopy (src , dst ),
)
case wasm .OpcodeMiscTableGrow :
tableIndex , num , err := leb128 .LoadUint32 (c .body [c .pc +1 :])
if err != nil {
return fmt .Errorf ("reading i32.const value: %v" , err )
}
c .pc += num
c .emit (
newOperationTableGrow (tableIndex ),
)
case wasm .OpcodeMiscTableSize :
tableIndex , num , err := leb128 .LoadUint32 (c .body [c .pc +1 :])
if err != nil {
return fmt .Errorf ("reading i32.const value: %v" , err )
}
c .pc += num
c .emit (
newOperationTableSize (tableIndex ),
)
case wasm .OpcodeMiscTableFill :
tableIndex , num , err := leb128 .LoadUint32 (c .body [c .pc +1 :])
if err != nil {
return fmt .Errorf ("reading i32.const value: %v" , err )
}
c .pc += num
c .emit (
newOperationTableFill (tableIndex ),
)
default :
return fmt .Errorf ("unsupported misc instruction in interpreterir: 0x%x" , op )
}
case wasm .OpcodeVecPrefix :
c .pc ++
switch vecOp := c .body [c .pc ]; vecOp {
case wasm .OpcodeVecV128Const :
c .pc ++
lo := binary .LittleEndian .Uint64 (c .body [c .pc : c .pc +8 ])
c .pc += 8
hi := binary .LittleEndian .Uint64 (c .body [c .pc : c .pc +8 ])
c .emit (
newOperationV128Const (lo , hi ),
)
c .pc += 7
case wasm .OpcodeVecV128Load :
arg , err := c .readMemoryArg (wasm .OpcodeI32LoadName )
if err != nil {
return err
}
c .emit (
newOperationV128Load (v128LoadType128 , arg ),
)
case wasm .OpcodeVecV128Load8x8s :
arg , err := c .readMemoryArg (wasm .OpcodeVecV128Load8x8SName )
if err != nil {
return err
}
c .emit (
newOperationV128Load (v128LoadType8x8s , arg ),
)
case wasm .OpcodeVecV128Load8x8u :
arg , err := c .readMemoryArg (wasm .OpcodeVecV128Load8x8UName )
if err != nil {
return err
}
c .emit (
newOperationV128Load (v128LoadType8x8u , arg ),
)
case wasm .OpcodeVecV128Load16x4s :
arg , err := c .readMemoryArg (wasm .OpcodeVecV128Load16x4SName )
if err != nil {
return err
}
c .emit (
newOperationV128Load (v128LoadType16x4s , arg ),
)
case wasm .OpcodeVecV128Load16x4u :
arg , err := c .readMemoryArg (wasm .OpcodeVecV128Load16x4UName )
if err != nil {
return err
}
c .emit (
newOperationV128Load (v128LoadType16x4u , arg ),
)
case wasm .OpcodeVecV128Load32x2s :
arg , err := c .readMemoryArg (wasm .OpcodeVecV128Load32x2SName )
if err != nil {
return err
}
c .emit (
newOperationV128Load (v128LoadType32x2s , arg ),
)
case wasm .OpcodeVecV128Load32x2u :
arg , err := c .readMemoryArg (wasm .OpcodeVecV128Load32x2UName )
if err != nil {
return err
}
c .emit (
newOperationV128Load (v128LoadType32x2u , arg ),
)
case wasm .OpcodeVecV128Load8Splat :
arg , err := c .readMemoryArg (wasm .OpcodeVecV128Load8SplatName )
if err != nil {
return err
}
c .emit (
newOperationV128Load (v128LoadType8Splat , arg ),
)
case wasm .OpcodeVecV128Load16Splat :
arg , err := c .readMemoryArg (wasm .OpcodeVecV128Load16SplatName )
if err != nil {
return err
}
c .emit (
newOperationV128Load (v128LoadType16Splat , arg ),
)
case wasm .OpcodeVecV128Load32Splat :
arg , err := c .readMemoryArg (wasm .OpcodeVecV128Load32SplatName )
if err != nil {
return err
}
c .emit (
newOperationV128Load (v128LoadType32Splat , arg ),
)
case wasm .OpcodeVecV128Load64Splat :
arg , err := c .readMemoryArg (wasm .OpcodeVecV128Load64SplatName )
if err != nil {
return err
}
c .emit (
newOperationV128Load (v128LoadType64Splat , arg ),
)
case wasm .OpcodeVecV128Load32zero :
arg , err := c .readMemoryArg (wasm .OpcodeVecV128Load32zeroName )
if err != nil {
return err
}
c .emit (
newOperationV128Load (v128LoadType32zero , arg ),
)
case wasm .OpcodeVecV128Load64zero :
arg , err := c .readMemoryArg (wasm .OpcodeVecV128Load64zeroName )
if err != nil {
return err
}
c .emit (
newOperationV128Load (v128LoadType64zero , arg ),
)
case wasm .OpcodeVecV128Load8Lane :
arg , err := c .readMemoryArg (wasm .OpcodeVecV128Load8LaneName )
if err != nil {
return err
}
c .pc ++
laneIndex := c .body [c .pc ]
c .emit (
newOperationV128LoadLane (laneIndex , 8 , arg ),
)
case wasm .OpcodeVecV128Load16Lane :
arg , err := c .readMemoryArg (wasm .OpcodeVecV128Load16LaneName )
if err != nil {
return err
}
c .pc ++
laneIndex := c .body [c .pc ]
c .emit (
newOperationV128LoadLane (laneIndex , 16 , arg ),
)
case wasm .OpcodeVecV128Load32Lane :
arg , err := c .readMemoryArg (wasm .OpcodeVecV128Load32LaneName )
if err != nil {
return err
}
c .pc ++
laneIndex := c .body [c .pc ]
c .emit (
newOperationV128LoadLane (laneIndex , 32 , arg ),
)
case wasm .OpcodeVecV128Load64Lane :
arg , err := c .readMemoryArg (wasm .OpcodeVecV128Load64LaneName )
if err != nil {
return err
}
c .pc ++
laneIndex := c .body [c .pc ]
c .emit (
newOperationV128LoadLane (laneIndex , 64 , arg ),
)
case wasm .OpcodeVecV128Store :
arg , err := c .readMemoryArg (wasm .OpcodeVecV128StoreName )
if err != nil {
return err
}
c .emit (
newOperationV128Store (arg ),
)
case wasm .OpcodeVecV128Store8Lane :
arg , err := c .readMemoryArg (wasm .OpcodeVecV128Store8LaneName )
if err != nil {
return err
}
c .pc ++
laneIndex := c .body [c .pc ]
c .emit (
newOperationV128StoreLane (laneIndex , 8 , arg ),
)
case wasm .OpcodeVecV128Store16Lane :
arg , err := c .readMemoryArg (wasm .OpcodeVecV128Store16LaneName )
if err != nil {
return err
}
c .pc ++
laneIndex := c .body [c .pc ]
c .emit (
newOperationV128StoreLane (laneIndex , 16 , arg ),
)
case wasm .OpcodeVecV128Store32Lane :
arg , err := c .readMemoryArg (wasm .OpcodeVecV128Store32LaneName )
if err != nil {
return err
}
c .pc ++
laneIndex := c .body [c .pc ]
c .emit (
newOperationV128StoreLane (laneIndex , 32 , arg ),
)
case wasm .OpcodeVecV128Store64Lane :
arg , err := c .readMemoryArg (wasm .OpcodeVecV128Store64LaneName )
if err != nil {
return err
}
c .pc ++
laneIndex := c .body [c .pc ]
c .emit (
newOperationV128StoreLane (laneIndex , 64 , arg ),
)
case wasm .OpcodeVecI8x16ExtractLaneS :
c .pc ++
laneIndex := c .body [c .pc ]
c .emit (
newOperationV128ExtractLane (laneIndex , true , shapeI8x16 ),
)
case wasm .OpcodeVecI8x16ExtractLaneU :
c .pc ++
laneIndex := c .body [c .pc ]
c .emit (
newOperationV128ExtractLane (laneIndex , false , shapeI8x16 ),
)
case wasm .OpcodeVecI16x8ExtractLaneS :
c .pc ++
laneIndex := c .body [c .pc ]
c .emit (
newOperationV128ExtractLane (laneIndex , true , shapeI16x8 ),
)
case wasm .OpcodeVecI16x8ExtractLaneU :
c .pc ++
laneIndex := c .body [c .pc ]
c .emit (
newOperationV128ExtractLane (laneIndex , false , shapeI16x8 ),
)
case wasm .OpcodeVecI32x4ExtractLane :
c .pc ++
laneIndex := c .body [c .pc ]
c .emit (
newOperationV128ExtractLane (laneIndex , false , shapeI32x4 ),
)
case wasm .OpcodeVecI64x2ExtractLane :
c .pc ++
laneIndex := c .body [c .pc ]
c .emit (
newOperationV128ExtractLane (laneIndex , false , shapeI64x2 ),
)
case wasm .OpcodeVecF32x4ExtractLane :
c .pc ++
laneIndex := c .body [c .pc ]
c .emit (
newOperationV128ExtractLane (laneIndex , false , shapeF32x4 ),
)
case wasm .OpcodeVecF64x2ExtractLane :
c .pc ++
laneIndex := c .body [c .pc ]
c .emit (
newOperationV128ExtractLane (laneIndex , false , shapeF64x2 ),
)
case wasm .OpcodeVecI8x16ReplaceLane :
c .pc ++
laneIndex := c .body [c .pc ]
c .emit (
newOperationV128ReplaceLane (laneIndex , shapeI8x16 ),
)
case wasm .OpcodeVecI16x8ReplaceLane :
c .pc ++
laneIndex := c .body [c .pc ]
c .emit (
newOperationV128ReplaceLane (laneIndex , shapeI16x8 ),
)
case wasm .OpcodeVecI32x4ReplaceLane :
c .pc ++
laneIndex := c .body [c .pc ]
c .emit (
newOperationV128ReplaceLane (laneIndex , shapeI32x4 ),
)
case wasm .OpcodeVecI64x2ReplaceLane :
c .pc ++
laneIndex := c .body [c .pc ]
c .emit (
newOperationV128ReplaceLane (laneIndex , shapeI64x2 ),
)
case wasm .OpcodeVecF32x4ReplaceLane :
c .pc ++
laneIndex := c .body [c .pc ]
c .emit (
newOperationV128ReplaceLane (laneIndex , shapeF32x4 ),
)
case wasm .OpcodeVecF64x2ReplaceLane :
c .pc ++
laneIndex := c .body [c .pc ]
c .emit (
newOperationV128ReplaceLane (laneIndex , shapeF64x2 ),
)
case wasm .OpcodeVecI8x16Splat :
c .emit (
newOperationV128Splat (shapeI8x16 ),
)
case wasm .OpcodeVecI16x8Splat :
c .emit (
newOperationV128Splat (shapeI16x8 ),
)
case wasm .OpcodeVecI32x4Splat :
c .emit (
newOperationV128Splat (shapeI32x4 ),
)
case wasm .OpcodeVecI64x2Splat :
c .emit (
newOperationV128Splat (shapeI64x2 ),
)
case wasm .OpcodeVecF32x4Splat :
c .emit (
newOperationV128Splat (shapeF32x4 ),
)
case wasm .OpcodeVecF64x2Splat :
c .emit (
newOperationV128Splat (shapeF64x2 ),
)
case wasm .OpcodeVecI8x16Swizzle :
c .emit (
newOperationV128Swizzle (),
)
case wasm .OpcodeVecV128i8x16Shuffle :
c .pc ++
lanes := make ([]uint64 , 16 )
for i := uint64 (0 ); i < 16 ; i ++ {
lanes [i ] = uint64 (c .body [c .pc +i ])
}
op := newOperationV128Shuffle (lanes )
c .emit (op )
c .pc += 15
case wasm .OpcodeVecV128AnyTrue :
c .emit (
newOperationV128AnyTrue (),
)
case wasm .OpcodeVecI8x16AllTrue :
c .emit (
newOperationV128AllTrue (shapeI8x16 ),
)
case wasm .OpcodeVecI16x8AllTrue :
c .emit (
newOperationV128AllTrue (shapeI16x8 ),
)
case wasm .OpcodeVecI32x4AllTrue :
c .emit (
newOperationV128AllTrue (shapeI32x4 ),
)
case wasm .OpcodeVecI64x2AllTrue :
c .emit (
newOperationV128AllTrue (shapeI64x2 ),
)
case wasm .OpcodeVecI8x16BitMask :
c .emit (
newOperationV128BitMask (shapeI8x16 ),
)
case wasm .OpcodeVecI16x8BitMask :
c .emit (
newOperationV128BitMask (shapeI16x8 ),
)
case wasm .OpcodeVecI32x4BitMask :
c .emit (
newOperationV128BitMask (shapeI32x4 ),
)
case wasm .OpcodeVecI64x2BitMask :
c .emit (
newOperationV128BitMask (shapeI64x2 ),
)
case wasm .OpcodeVecV128And :
c .emit (
newOperationV128And (),
)
case wasm .OpcodeVecV128Not :
c .emit (
newOperationV128Not (),
)
case wasm .OpcodeVecV128Or :
c .emit (
newOperationV128Or (),
)
case wasm .OpcodeVecV128Xor :
c .emit (
newOperationV128Xor (),
)
case wasm .OpcodeVecV128Bitselect :
c .emit (
newOperationV128Bitselect (),
)
case wasm .OpcodeVecV128AndNot :
c .emit (
newOperationV128AndNot (),
)
case wasm .OpcodeVecI8x16Shl :
c .emit (
newOperationV128Shl (shapeI8x16 ),
)
case wasm .OpcodeVecI8x16ShrS :
c .emit (
newOperationV128Shr (shapeI8x16 , true ),
)
case wasm .OpcodeVecI8x16ShrU :
c .emit (
newOperationV128Shr (shapeI8x16 , false ),
)
case wasm .OpcodeVecI16x8Shl :
c .emit (
newOperationV128Shl (shapeI16x8 ),
)
case wasm .OpcodeVecI16x8ShrS :
c .emit (
newOperationV128Shr (shapeI16x8 , true ),
)
case wasm .OpcodeVecI16x8ShrU :
c .emit (
newOperationV128Shr (shapeI16x8 , false ),
)
case wasm .OpcodeVecI32x4Shl :
c .emit (
newOperationV128Shl (shapeI32x4 ),
)
case wasm .OpcodeVecI32x4ShrS :
c .emit (
newOperationV128Shr (shapeI32x4 , true ),
)
case wasm .OpcodeVecI32x4ShrU :
c .emit (
newOperationV128Shr (shapeI32x4 , false ),
)
case wasm .OpcodeVecI64x2Shl :
c .emit (
newOperationV128Shl (shapeI64x2 ),
)
case wasm .OpcodeVecI64x2ShrS :
c .emit (
newOperationV128Shr (shapeI64x2 , true ),
)
case wasm .OpcodeVecI64x2ShrU :
c .emit (
newOperationV128Shr (shapeI64x2 , false ),
)
case wasm .OpcodeVecI8x16Eq :
c .emit (
newOperationV128Cmp (v128CmpTypeI8x16Eq ),
)
case wasm .OpcodeVecI8x16Ne :
c .emit (
newOperationV128Cmp (v128CmpTypeI8x16Ne ),
)
case wasm .OpcodeVecI8x16LtS :
c .emit (
newOperationV128Cmp (v128CmpTypeI8x16LtS ),
)
case wasm .OpcodeVecI8x16LtU :
c .emit (
newOperationV128Cmp (v128CmpTypeI8x16LtU ),
)
case wasm .OpcodeVecI8x16GtS :
c .emit (
newOperationV128Cmp (v128CmpTypeI8x16GtS ),
)
case wasm .OpcodeVecI8x16GtU :
c .emit (
newOperationV128Cmp (v128CmpTypeI8x16GtU ),
)
case wasm .OpcodeVecI8x16LeS :
c .emit (
newOperationV128Cmp (v128CmpTypeI8x16LeS ),
)
case wasm .OpcodeVecI8x16LeU :
c .emit (
newOperationV128Cmp (v128CmpTypeI8x16LeU ),
)
case wasm .OpcodeVecI8x16GeS :
c .emit (
newOperationV128Cmp (v128CmpTypeI8x16GeS ),
)
case wasm .OpcodeVecI8x16GeU :
c .emit (
newOperationV128Cmp (v128CmpTypeI8x16GeU ),
)
case wasm .OpcodeVecI16x8Eq :
c .emit (
newOperationV128Cmp (v128CmpTypeI16x8Eq ),
)
case wasm .OpcodeVecI16x8Ne :
c .emit (
newOperationV128Cmp (v128CmpTypeI16x8Ne ),
)
case wasm .OpcodeVecI16x8LtS :
c .emit (
newOperationV128Cmp (v128CmpTypeI16x8LtS ),
)
case wasm .OpcodeVecI16x8LtU :
c .emit (
newOperationV128Cmp (v128CmpTypeI16x8LtU ),
)
case wasm .OpcodeVecI16x8GtS :
c .emit (
newOperationV128Cmp (v128CmpTypeI16x8GtS ),
)
case wasm .OpcodeVecI16x8GtU :
c .emit (
newOperationV128Cmp (v128CmpTypeI16x8GtU ),
)
case wasm .OpcodeVecI16x8LeS :
c .emit (
newOperationV128Cmp (v128CmpTypeI16x8LeS ),
)
case wasm .OpcodeVecI16x8LeU :
c .emit (
newOperationV128Cmp (v128CmpTypeI16x8LeU ),
)
case wasm .OpcodeVecI16x8GeS :
c .emit (
newOperationV128Cmp (v128CmpTypeI16x8GeS ),
)
case wasm .OpcodeVecI16x8GeU :
c .emit (
newOperationV128Cmp (v128CmpTypeI16x8GeU ),
)
case wasm .OpcodeVecI32x4Eq :
c .emit (
newOperationV128Cmp (v128CmpTypeI32x4Eq ),
)
case wasm .OpcodeVecI32x4Ne :
c .emit (
newOperationV128Cmp (v128CmpTypeI32x4Ne ),
)
case wasm .OpcodeVecI32x4LtS :
c .emit (
newOperationV128Cmp (v128CmpTypeI32x4LtS ),
)
case wasm .OpcodeVecI32x4LtU :
c .emit (
newOperationV128Cmp (v128CmpTypeI32x4LtU ),
)
case wasm .OpcodeVecI32x4GtS :
c .emit (
newOperationV128Cmp (v128CmpTypeI32x4GtS ),
)
case wasm .OpcodeVecI32x4GtU :
c .emit (
newOperationV128Cmp (v128CmpTypeI32x4GtU ),
)
case wasm .OpcodeVecI32x4LeS :
c .emit (
newOperationV128Cmp (v128CmpTypeI32x4LeS ),
)
case wasm .OpcodeVecI32x4LeU :
c .emit (
newOperationV128Cmp (v128CmpTypeI32x4LeU ),
)
case wasm .OpcodeVecI32x4GeS :
c .emit (
newOperationV128Cmp (v128CmpTypeI32x4GeS ),
)
case wasm .OpcodeVecI32x4GeU :
c .emit (
newOperationV128Cmp (v128CmpTypeI32x4GeU ),
)
case wasm .OpcodeVecI64x2Eq :
c .emit (
newOperationV128Cmp (v128CmpTypeI64x2Eq ),
)
case wasm .OpcodeVecI64x2Ne :
c .emit (
newOperationV128Cmp (v128CmpTypeI64x2Ne ),
)
case wasm .OpcodeVecI64x2LtS :
c .emit (
newOperationV128Cmp (v128CmpTypeI64x2LtS ),
)
case wasm .OpcodeVecI64x2GtS :
c .emit (
newOperationV128Cmp (v128CmpTypeI64x2GtS ),
)
case wasm .OpcodeVecI64x2LeS :
c .emit (
newOperationV128Cmp (v128CmpTypeI64x2LeS ),
)
case wasm .OpcodeVecI64x2GeS :
c .emit (
newOperationV128Cmp (v128CmpTypeI64x2GeS ),
)
case wasm .OpcodeVecF32x4Eq :
c .emit (
newOperationV128Cmp (v128CmpTypeF32x4Eq ),
)
case wasm .OpcodeVecF32x4Ne :
c .emit (
newOperationV128Cmp (v128CmpTypeF32x4Ne ),
)
case wasm .OpcodeVecF32x4Lt :
c .emit (
newOperationV128Cmp (v128CmpTypeF32x4Lt ),
)
case wasm .OpcodeVecF32x4Gt :
c .emit (
newOperationV128Cmp (v128CmpTypeF32x4Gt ),
)
case wasm .OpcodeVecF32x4Le :
c .emit (
newOperationV128Cmp (v128CmpTypeF32x4Le ),
)
case wasm .OpcodeVecF32x4Ge :
c .emit (
newOperationV128Cmp (v128CmpTypeF32x4Ge ),
)
case wasm .OpcodeVecF64x2Eq :
c .emit (
newOperationV128Cmp (v128CmpTypeF64x2Eq ),
)
case wasm .OpcodeVecF64x2Ne :
c .emit (
newOperationV128Cmp (v128CmpTypeF64x2Ne ),
)
case wasm .OpcodeVecF64x2Lt :
c .emit (
newOperationV128Cmp (v128CmpTypeF64x2Lt ),
)
case wasm .OpcodeVecF64x2Gt :
c .emit (
newOperationV128Cmp (v128CmpTypeF64x2Gt ),
)
case wasm .OpcodeVecF64x2Le :
c .emit (
newOperationV128Cmp (v128CmpTypeF64x2Le ),
)
case wasm .OpcodeVecF64x2Ge :
c .emit (
newOperationV128Cmp (v128CmpTypeF64x2Ge ),
)
case wasm .OpcodeVecI8x16Neg :
c .emit (
newOperationV128Neg (shapeI8x16 ),
)
case wasm .OpcodeVecI16x8Neg :
c .emit (
newOperationV128Neg (shapeI16x8 ),
)
case wasm .OpcodeVecI32x4Neg :
c .emit (
newOperationV128Neg (shapeI32x4 ),
)
case wasm .OpcodeVecI64x2Neg :
c .emit (
newOperationV128Neg (shapeI64x2 ),
)
case wasm .OpcodeVecF32x4Neg :
c .emit (
newOperationV128Neg (shapeF32x4 ),
)
case wasm .OpcodeVecF64x2Neg :
c .emit (
newOperationV128Neg (shapeF64x2 ),
)
case wasm .OpcodeVecI8x16Add :
c .emit (
newOperationV128Add (shapeI8x16 ),
)
case wasm .OpcodeVecI16x8Add :
c .emit (
newOperationV128Add (shapeI16x8 ),
)
case wasm .OpcodeVecI32x4Add :
c .emit (
newOperationV128Add (shapeI32x4 ),
)
case wasm .OpcodeVecI64x2Add :
c .emit (
newOperationV128Add (shapeI64x2 ),
)
case wasm .OpcodeVecF32x4Add :
c .emit (
newOperationV128Add (shapeF32x4 ),
)
case wasm .OpcodeVecF64x2Add :
c .emit (
newOperationV128Add (shapeF64x2 ),
)
case wasm .OpcodeVecI8x16Sub :
c .emit (
newOperationV128Sub (shapeI8x16 ),
)
case wasm .OpcodeVecI16x8Sub :
c .emit (
newOperationV128Sub (shapeI16x8 ),
)
case wasm .OpcodeVecI32x4Sub :
c .emit (
newOperationV128Sub (shapeI32x4 ),
)
case wasm .OpcodeVecI64x2Sub :
c .emit (
newOperationV128Sub (shapeI64x2 ),
)
case wasm .OpcodeVecF32x4Sub :
c .emit (
newOperationV128Sub (shapeF32x4 ),
)
case wasm .OpcodeVecF64x2Sub :
c .emit (
newOperationV128Sub (shapeF64x2 ),
)
case wasm .OpcodeVecI8x16AddSatS :
c .emit (
newOperationV128AddSat (shapeI8x16 , true ),
)
case wasm .OpcodeVecI8x16AddSatU :
c .emit (
newOperationV128AddSat (shapeI8x16 , false ),
)
case wasm .OpcodeVecI16x8AddSatS :
c .emit (
newOperationV128AddSat (shapeI16x8 , true ),
)
case wasm .OpcodeVecI16x8AddSatU :
c .emit (
newOperationV128AddSat (shapeI16x8 , false ),
)
case wasm .OpcodeVecI8x16SubSatS :
c .emit (
newOperationV128SubSat (shapeI8x16 , true ),
)
case wasm .OpcodeVecI8x16SubSatU :
c .emit (
newOperationV128SubSat (shapeI8x16 , false ),
)
case wasm .OpcodeVecI16x8SubSatS :
c .emit (
newOperationV128SubSat (shapeI16x8 , true ),
)
case wasm .OpcodeVecI16x8SubSatU :
c .emit (
newOperationV128SubSat (shapeI16x8 , false ),
)
case wasm .OpcodeVecI16x8Mul :
c .emit (
newOperationV128Mul (shapeI16x8 ),
)
case wasm .OpcodeVecI32x4Mul :
c .emit (
newOperationV128Mul (shapeI32x4 ),
)
case wasm .OpcodeVecI64x2Mul :
c .emit (
newOperationV128Mul (shapeI64x2 ),
)
case wasm .OpcodeVecF32x4Mul :
c .emit (
newOperationV128Mul (shapeF32x4 ),
)
case wasm .OpcodeVecF64x2Mul :
c .emit (
newOperationV128Mul (shapeF64x2 ),
)
case wasm .OpcodeVecF32x4Sqrt :
c .emit (
newOperationV128Sqrt (shapeF32x4 ),
)
case wasm .OpcodeVecF64x2Sqrt :
c .emit (
newOperationV128Sqrt (shapeF64x2 ),
)
case wasm .OpcodeVecF32x4Div :
c .emit (
newOperationV128Div (shapeF32x4 ),
)
case wasm .OpcodeVecF64x2Div :
c .emit (
newOperationV128Div (shapeF64x2 ),
)
case wasm .OpcodeVecI8x16Abs :
c .emit (
newOperationV128Abs (shapeI8x16 ),
)
case wasm .OpcodeVecI8x16Popcnt :
c .emit (
newOperationV128Popcnt (shapeI8x16 ),
)
case wasm .OpcodeVecI16x8Abs :
c .emit (
newOperationV128Abs (shapeI16x8 ),
)
case wasm .OpcodeVecI32x4Abs :
c .emit (
newOperationV128Abs (shapeI32x4 ),
)
case wasm .OpcodeVecI64x2Abs :
c .emit (
newOperationV128Abs (shapeI64x2 ),
)
case wasm .OpcodeVecF32x4Abs :
c .emit (
newOperationV128Abs (shapeF32x4 ),
)
case wasm .OpcodeVecF64x2Abs :
c .emit (
newOperationV128Abs (shapeF64x2 ),
)
case wasm .OpcodeVecI8x16MinS :
c .emit (
newOperationV128Min (shapeI8x16 , true ),
)
case wasm .OpcodeVecI8x16MinU :
c .emit (
newOperationV128Min (shapeI8x16 , false ),
)
case wasm .OpcodeVecI8x16MaxS :
c .emit (
newOperationV128Max (shapeI8x16 , true ),
)
case wasm .OpcodeVecI8x16MaxU :
c .emit (
newOperationV128Max (shapeI8x16 , false ),
)
case wasm .OpcodeVecI8x16AvgrU :
c .emit (
newOperationV128AvgrU (shapeI8x16 ),
)
case wasm .OpcodeVecI16x8MinS :
c .emit (
newOperationV128Min (shapeI16x8 , true ),
)
case wasm .OpcodeVecI16x8MinU :
c .emit (
newOperationV128Min (shapeI16x8 , false ),
)
case wasm .OpcodeVecI16x8MaxS :
c .emit (
newOperationV128Max (shapeI16x8 , true ),
)
case wasm .OpcodeVecI16x8MaxU :
c .emit (
newOperationV128Max (shapeI16x8 , false ),
)
case wasm .OpcodeVecI16x8AvgrU :
c .emit (
newOperationV128AvgrU (shapeI16x8 ),
)
case wasm .OpcodeVecI32x4MinS :
c .emit (
newOperationV128Min (shapeI32x4 , true ),
)
case wasm .OpcodeVecI32x4MinU :
c .emit (
newOperationV128Min (shapeI32x4 , false ),
)
case wasm .OpcodeVecI32x4MaxS :
c .emit (
newOperationV128Max (shapeI32x4 , true ),
)
case wasm .OpcodeVecI32x4MaxU :
c .emit (
newOperationV128Max (shapeI32x4 , false ),
)
case wasm .OpcodeVecF32x4Min :
c .emit (
newOperationV128Min (shapeF32x4 , false ),
)
case wasm .OpcodeVecF32x4Max :
c .emit (
newOperationV128Max (shapeF32x4 , false ),
)
case wasm .OpcodeVecF64x2Min :
c .emit (
newOperationV128Min (shapeF64x2 , false ),
)
case wasm .OpcodeVecF64x2Max :
c .emit (
newOperationV128Max (shapeF64x2 , false ),
)
case wasm .OpcodeVecF32x4Pmin :
c .emit (
newOperationV128Pmin (shapeF32x4 ),
)
case wasm .OpcodeVecF32x4Pmax :
c .emit (
newOperationV128Pmax (shapeF32x4 ),
)
case wasm .OpcodeVecF64x2Pmin :
c .emit (
newOperationV128Pmin (shapeF64x2 ),
)
case wasm .OpcodeVecF64x2Pmax :
c .emit (
newOperationV128Pmax (shapeF64x2 ),
)
case wasm .OpcodeVecF32x4Ceil :
c .emit (
newOperationV128Ceil (shapeF32x4 ),
)
case wasm .OpcodeVecF32x4Floor :
c .emit (
newOperationV128Floor (shapeF32x4 ),
)
case wasm .OpcodeVecF32x4Trunc :
c .emit (
newOperationV128Trunc (shapeF32x4 ),
)
case wasm .OpcodeVecF32x4Nearest :
c .emit (
newOperationV128Nearest (shapeF32x4 ),
)
case wasm .OpcodeVecF64x2Ceil :
c .emit (
newOperationV128Ceil (shapeF64x2 ),
)
case wasm .OpcodeVecF64x2Floor :
c .emit (
newOperationV128Floor (shapeF64x2 ),
)
case wasm .OpcodeVecF64x2Trunc :
c .emit (
newOperationV128Trunc (shapeF64x2 ),
)
case wasm .OpcodeVecF64x2Nearest :
c .emit (
newOperationV128Nearest (shapeF64x2 ),
)
case wasm .OpcodeVecI16x8ExtendLowI8x16S :
c .emit (
newOperationV128Extend (shapeI8x16 , true , true ),
)
case wasm .OpcodeVecI16x8ExtendHighI8x16S :
c .emit (
newOperationV128Extend (shapeI8x16 , true , false ),
)
case wasm .OpcodeVecI16x8ExtendLowI8x16U :
c .emit (
newOperationV128Extend (shapeI8x16 , false , true ),
)
case wasm .OpcodeVecI16x8ExtendHighI8x16U :
c .emit (
newOperationV128Extend (shapeI8x16 , false , false ),
)
case wasm .OpcodeVecI32x4ExtendLowI16x8S :
c .emit (
newOperationV128Extend (shapeI16x8 , true , true ),
)
case wasm .OpcodeVecI32x4ExtendHighI16x8S :
c .emit (
newOperationV128Extend (shapeI16x8 , true , false ),
)
case wasm .OpcodeVecI32x4ExtendLowI16x8U :
c .emit (
newOperationV128Extend (shapeI16x8 , false , true ),
)
case wasm .OpcodeVecI32x4ExtendHighI16x8U :
c .emit (
newOperationV128Extend (shapeI16x8 , false , false ),
)
case wasm .OpcodeVecI64x2ExtendLowI32x4S :
c .emit (
newOperationV128Extend (shapeI32x4 , true , true ),
)
case wasm .OpcodeVecI64x2ExtendHighI32x4S :
c .emit (
newOperationV128Extend (shapeI32x4 , true , false ),
)
case wasm .OpcodeVecI64x2ExtendLowI32x4U :
c .emit (
newOperationV128Extend (shapeI32x4 , false , true ),
)
case wasm .OpcodeVecI64x2ExtendHighI32x4U :
c .emit (
newOperationV128Extend (shapeI32x4 , false , false ),
)
case wasm .OpcodeVecI16x8Q15mulrSatS :
c .emit (
newOperationV128Q15mulrSatS (),
)
case wasm .OpcodeVecI16x8ExtMulLowI8x16S :
c .emit (
newOperationV128ExtMul (shapeI8x16 , true , true ),
)
case wasm .OpcodeVecI16x8ExtMulHighI8x16S :
c .emit (
newOperationV128ExtMul (shapeI8x16 , true , false ),
)
case wasm .OpcodeVecI16x8ExtMulLowI8x16U :
c .emit (
newOperationV128ExtMul (shapeI8x16 , false , true ),
)
case wasm .OpcodeVecI16x8ExtMulHighI8x16U :
c .emit (
newOperationV128ExtMul (shapeI8x16 , false , false ),
)
case wasm .OpcodeVecI32x4ExtMulLowI16x8S :
c .emit (
newOperationV128ExtMul (shapeI16x8 , true , true ),
)
case wasm .OpcodeVecI32x4ExtMulHighI16x8S :
c .emit (
newOperationV128ExtMul (shapeI16x8 , true , false ),
)
case wasm .OpcodeVecI32x4ExtMulLowI16x8U :
c .emit (
newOperationV128ExtMul (shapeI16x8 , false , true ),
)
case wasm .OpcodeVecI32x4ExtMulHighI16x8U :
c .emit (
newOperationV128ExtMul (shapeI16x8 , false , false ),
)
case wasm .OpcodeVecI64x2ExtMulLowI32x4S :
c .emit (
newOperationV128ExtMul (shapeI32x4 , true , true ),
)
case wasm .OpcodeVecI64x2ExtMulHighI32x4S :
c .emit (
newOperationV128ExtMul (shapeI32x4 , true , false ),
)
case wasm .OpcodeVecI64x2ExtMulLowI32x4U :
c .emit (
newOperationV128ExtMul (shapeI32x4 , false , true ),
)
case wasm .OpcodeVecI64x2ExtMulHighI32x4U :
c .emit (
newOperationV128ExtMul (shapeI32x4 , false , false ),
)
case wasm .OpcodeVecI16x8ExtaddPairwiseI8x16S :
c .emit (
newOperationV128ExtAddPairwise (shapeI8x16 , true ),
)
case wasm .OpcodeVecI16x8ExtaddPairwiseI8x16U :
c .emit (
newOperationV128ExtAddPairwise (shapeI8x16 , false ),
)
case wasm .OpcodeVecI32x4ExtaddPairwiseI16x8S :
c .emit (
newOperationV128ExtAddPairwise (shapeI16x8 , true ),
)
case wasm .OpcodeVecI32x4ExtaddPairwiseI16x8U :
c .emit (
newOperationV128ExtAddPairwise (shapeI16x8 , false ),
)
case wasm .OpcodeVecF64x2PromoteLowF32x4Zero :
c .emit (
newOperationV128FloatPromote (),
)
case wasm .OpcodeVecF32x4DemoteF64x2Zero :
c .emit (
newOperationV128FloatDemote (),
)
case wasm .OpcodeVecF32x4ConvertI32x4S :
c .emit (
newOperationV128FConvertFromI (shapeF32x4 , true ),
)
case wasm .OpcodeVecF32x4ConvertI32x4U :
c .emit (
newOperationV128FConvertFromI (shapeF32x4 , false ),
)
case wasm .OpcodeVecF64x2ConvertLowI32x4S :
c .emit (
newOperationV128FConvertFromI (shapeF64x2 , true ),
)
case wasm .OpcodeVecF64x2ConvertLowI32x4U :
c .emit (
newOperationV128FConvertFromI (shapeF64x2 , false ),
)
case wasm .OpcodeVecI32x4DotI16x8S :
c .emit (
newOperationV128Dot (),
)
case wasm .OpcodeVecI8x16NarrowI16x8S :
c .emit (
newOperationV128Narrow (shapeI16x8 , true ),
)
case wasm .OpcodeVecI8x16NarrowI16x8U :
c .emit (
newOperationV128Narrow (shapeI16x8 , false ),
)
case wasm .OpcodeVecI16x8NarrowI32x4S :
c .emit (
newOperationV128Narrow (shapeI32x4 , true ),
)
case wasm .OpcodeVecI16x8NarrowI32x4U :
c .emit (
newOperationV128Narrow (shapeI32x4 , false ),
)
case wasm .OpcodeVecI32x4TruncSatF32x4S :
c .emit (
newOperationV128ITruncSatFromF (shapeF32x4 , true ),
)
case wasm .OpcodeVecI32x4TruncSatF32x4U :
c .emit (
newOperationV128ITruncSatFromF (shapeF32x4 , false ),
)
case wasm .OpcodeVecI32x4TruncSatF64x2SZero :
c .emit (
newOperationV128ITruncSatFromF (shapeF64x2 , true ),
)
case wasm .OpcodeVecI32x4TruncSatF64x2UZero :
c .emit (
newOperationV128ITruncSatFromF (shapeF64x2 , false ),
)
default :
return fmt .Errorf ("unsupported vector instruction in interpreterir: %s" , wasm .VectorInstructionName (vecOp ))
}
case wasm .OpcodeAtomicPrefix :
c .pc ++
atomicOp := c .body [c .pc ]
switch atomicOp {
case wasm .OpcodeAtomicMemoryWait32 :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicMemoryWait32Name )
if err != nil {
return err
}
c .emit (
newOperationAtomicMemoryWait (unsignedTypeI32 , imm ),
)
case wasm .OpcodeAtomicMemoryWait64 :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicMemoryWait64Name )
if err != nil {
return err
}
c .emit (
newOperationAtomicMemoryWait (unsignedTypeI64 , imm ),
)
case wasm .OpcodeAtomicMemoryNotify :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicMemoryNotifyName )
if err != nil {
return err
}
c .emit (
newOperationAtomicMemoryNotify (imm ),
)
case wasm .OpcodeAtomicFence :
c .pc ++
_ = c .body [c .pc ]
c .emit (
newOperationAtomicFence (),
)
case wasm .OpcodeAtomicI32Load :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32LoadName )
if err != nil {
return err
}
c .emit (
newOperationAtomicLoad (unsignedTypeI32 , imm ),
)
case wasm .OpcodeAtomicI64Load :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64LoadName )
if err != nil {
return err
}
c .emit (
newOperationAtomicLoad (unsignedTypeI64 , imm ),
)
case wasm .OpcodeAtomicI32Load8U :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32Load8UName )
if err != nil {
return err
}
c .emit (
newOperationAtomicLoad8 (unsignedTypeI32 , imm ),
)
case wasm .OpcodeAtomicI32Load16U :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32Load16UName )
if err != nil {
return err
}
c .emit (
newOperationAtomicLoad16 (unsignedTypeI32 , imm ),
)
case wasm .OpcodeAtomicI64Load8U :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Load8UName )
if err != nil {
return err
}
c .emit (
newOperationAtomicLoad8 (unsignedTypeI64 , imm ),
)
case wasm .OpcodeAtomicI64Load16U :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Load16UName )
if err != nil {
return err
}
c .emit (
newOperationAtomicLoad16 (unsignedTypeI64 , imm ),
)
case wasm .OpcodeAtomicI64Load32U :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Load32UName )
if err != nil {
return err
}
c .emit (
newOperationAtomicLoad (unsignedTypeI32 , imm ),
)
case wasm .OpcodeAtomicI32Store :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32StoreName )
if err != nil {
return err
}
c .emit (
newOperationAtomicStore (unsignedTypeI32 , imm ),
)
case wasm .OpcodeAtomicI32Store8 :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32Store8Name )
if err != nil {
return err
}
c .emit (
newOperationAtomicStore8 (unsignedTypeI32 , imm ),
)
case wasm .OpcodeAtomicI32Store16 :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32Store16Name )
if err != nil {
return err
}
c .emit (
newOperationAtomicStore16 (unsignedTypeI32 , imm ),
)
case wasm .OpcodeAtomicI64Store :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64StoreName )
if err != nil {
return err
}
c .emit (
newOperationAtomicStore (unsignedTypeI64 , imm ),
)
case wasm .OpcodeAtomicI64Store8 :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Store8Name )
if err != nil {
return err
}
c .emit (
newOperationAtomicStore8 (unsignedTypeI64 , imm ),
)
case wasm .OpcodeAtomicI64Store16 :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Store16Name )
if err != nil {
return err
}
c .emit (
newOperationAtomicStore16 (unsignedTypeI64 , imm ),
)
case wasm .OpcodeAtomicI64Store32 :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Store32Name )
if err != nil {
return err
}
c .emit (
newOperationAtomicStore (unsignedTypeI32 , imm ),
)
case wasm .OpcodeAtomicI32RmwAdd :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32RmwAddName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW (unsignedTypeI32 , imm , atomicArithmeticOpAdd ),
)
case wasm .OpcodeAtomicI64RmwAdd :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64RmwAddName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW (unsignedTypeI64 , imm , atomicArithmeticOpAdd ),
)
case wasm .OpcodeAtomicI32Rmw8AddU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32Rmw8AddUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW8 (unsignedTypeI32 , imm , atomicArithmeticOpAdd ),
)
case wasm .OpcodeAtomicI64Rmw8AddU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Rmw8AddUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW8 (unsignedTypeI64 , imm , atomicArithmeticOpAdd ),
)
case wasm .OpcodeAtomicI32Rmw16AddU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32Rmw16AddUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW16 (unsignedTypeI32 , imm , atomicArithmeticOpAdd ),
)
case wasm .OpcodeAtomicI64Rmw16AddU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Rmw16AddUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW16 (unsignedTypeI64 , imm , atomicArithmeticOpAdd ),
)
case wasm .OpcodeAtomicI64Rmw32AddU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Rmw32AddUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW (unsignedTypeI32 , imm , atomicArithmeticOpAdd ),
)
case wasm .OpcodeAtomicI32RmwSub :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32RmwSubName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW (unsignedTypeI32 , imm , atomicArithmeticOpSub ),
)
case wasm .OpcodeAtomicI64RmwSub :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64RmwSubName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW (unsignedTypeI64 , imm , atomicArithmeticOpSub ),
)
case wasm .OpcodeAtomicI32Rmw8SubU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32Rmw8SubUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW8 (unsignedTypeI32 , imm , atomicArithmeticOpSub ),
)
case wasm .OpcodeAtomicI64Rmw8SubU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Rmw8SubUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW8 (unsignedTypeI64 , imm , atomicArithmeticOpSub ),
)
case wasm .OpcodeAtomicI32Rmw16SubU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32Rmw16SubUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW16 (unsignedTypeI32 , imm , atomicArithmeticOpSub ),
)
case wasm .OpcodeAtomicI64Rmw16SubU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Rmw16SubUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW16 (unsignedTypeI64 , imm , atomicArithmeticOpSub ),
)
case wasm .OpcodeAtomicI64Rmw32SubU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Rmw32SubUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW (unsignedTypeI32 , imm , atomicArithmeticOpSub ),
)
case wasm .OpcodeAtomicI32RmwAnd :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32RmwAndName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW (unsignedTypeI32 , imm , atomicArithmeticOpAnd ),
)
case wasm .OpcodeAtomicI64RmwAnd :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64RmwAndName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW (unsignedTypeI64 , imm , atomicArithmeticOpAnd ),
)
case wasm .OpcodeAtomicI32Rmw8AndU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32Rmw8AndUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW8 (unsignedTypeI32 , imm , atomicArithmeticOpAnd ),
)
case wasm .OpcodeAtomicI64Rmw8AndU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Rmw8AndUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW8 (unsignedTypeI64 , imm , atomicArithmeticOpAnd ),
)
case wasm .OpcodeAtomicI32Rmw16AndU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32Rmw16AndUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW16 (unsignedTypeI32 , imm , atomicArithmeticOpAnd ),
)
case wasm .OpcodeAtomicI64Rmw16AndU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Rmw16AndUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW16 (unsignedTypeI64 , imm , atomicArithmeticOpAnd ),
)
case wasm .OpcodeAtomicI64Rmw32AndU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Rmw32AndUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW (unsignedTypeI32 , imm , atomicArithmeticOpAnd ),
)
case wasm .OpcodeAtomicI32RmwOr :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32RmwOrName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW (unsignedTypeI32 , imm , atomicArithmeticOpOr ),
)
case wasm .OpcodeAtomicI64RmwOr :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64RmwOrName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW (unsignedTypeI64 , imm , atomicArithmeticOpOr ),
)
case wasm .OpcodeAtomicI32Rmw8OrU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32Rmw8OrUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW8 (unsignedTypeI32 , imm , atomicArithmeticOpOr ),
)
case wasm .OpcodeAtomicI64Rmw8OrU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Rmw8OrUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW8 (unsignedTypeI64 , imm , atomicArithmeticOpOr ),
)
case wasm .OpcodeAtomicI32Rmw16OrU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32Rmw16OrUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW16 (unsignedTypeI32 , imm , atomicArithmeticOpOr ),
)
case wasm .OpcodeAtomicI64Rmw16OrU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Rmw16OrUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW16 (unsignedTypeI64 , imm , atomicArithmeticOpOr ),
)
case wasm .OpcodeAtomicI64Rmw32OrU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Rmw32OrUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW (unsignedTypeI32 , imm , atomicArithmeticOpOr ),
)
case wasm .OpcodeAtomicI32RmwXor :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32RmwXorName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW (unsignedTypeI32 , imm , atomicArithmeticOpXor ),
)
case wasm .OpcodeAtomicI64RmwXor :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64RmwXorName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW (unsignedTypeI64 , imm , atomicArithmeticOpXor ),
)
case wasm .OpcodeAtomicI32Rmw8XorU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32Rmw8XorUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW8 (unsignedTypeI32 , imm , atomicArithmeticOpXor ),
)
case wasm .OpcodeAtomicI64Rmw8XorU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Rmw8XorUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW8 (unsignedTypeI64 , imm , atomicArithmeticOpXor ),
)
case wasm .OpcodeAtomicI32Rmw16XorU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32Rmw16XorUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW16 (unsignedTypeI32 , imm , atomicArithmeticOpXor ),
)
case wasm .OpcodeAtomicI64Rmw16XorU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Rmw16XorUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW16 (unsignedTypeI64 , imm , atomicArithmeticOpXor ),
)
case wasm .OpcodeAtomicI64Rmw32XorU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Rmw32XorUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW (unsignedTypeI32 , imm , atomicArithmeticOpXor ),
)
case wasm .OpcodeAtomicI32RmwXchg :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32RmwXchgName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW (unsignedTypeI32 , imm , atomicArithmeticOpNop ),
)
case wasm .OpcodeAtomicI64RmwXchg :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64RmwXchgName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW (unsignedTypeI64 , imm , atomicArithmeticOpNop ),
)
case wasm .OpcodeAtomicI32Rmw8XchgU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32Rmw8XchgUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW8 (unsignedTypeI32 , imm , atomicArithmeticOpNop ),
)
case wasm .OpcodeAtomicI64Rmw8XchgU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Rmw8XchgUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW8 (unsignedTypeI64 , imm , atomicArithmeticOpNop ),
)
case wasm .OpcodeAtomicI32Rmw16XchgU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32Rmw16XchgUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW16 (unsignedTypeI32 , imm , atomicArithmeticOpNop ),
)
case wasm .OpcodeAtomicI64Rmw16XchgU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Rmw16XchgUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW16 (unsignedTypeI64 , imm , atomicArithmeticOpNop ),
)
case wasm .OpcodeAtomicI64Rmw32XchgU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Rmw32XchgUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW (unsignedTypeI32 , imm , atomicArithmeticOpNop ),
)
case wasm .OpcodeAtomicI32RmwCmpxchg :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32RmwCmpxchgName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMWCmpxchg (unsignedTypeI32 , imm ),
)
case wasm .OpcodeAtomicI64RmwCmpxchg :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64RmwCmpxchgName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMWCmpxchg (unsignedTypeI64 , imm ),
)
case wasm .OpcodeAtomicI32Rmw8CmpxchgU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32Rmw8CmpxchgUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW8Cmpxchg (unsignedTypeI32 , imm ),
)
case wasm .OpcodeAtomicI64Rmw8CmpxchgU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Rmw8CmpxchgUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW8Cmpxchg (unsignedTypeI64 , imm ),
)
case wasm .OpcodeAtomicI32Rmw16CmpxchgU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI32Rmw16CmpxchgUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW16Cmpxchg (unsignedTypeI32 , imm ),
)
case wasm .OpcodeAtomicI64Rmw16CmpxchgU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Rmw16CmpxchgUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMW16Cmpxchg (unsignedTypeI64 , imm ),
)
case wasm .OpcodeAtomicI64Rmw32CmpxchgU :
imm , err := c .readMemoryArg (wasm .OpcodeAtomicI64Rmw32CmpxchgUName )
if err != nil {
return err
}
c .emit (
newOperationAtomicRMWCmpxchg (unsignedTypeI32 , imm ),
)
default :
return fmt .Errorf ("unsupported atomic instruction in interpreterir: %s" , wasm .AtomicInstructionName (atomicOp ))
}
default :
return fmt .Errorf ("unsupported instruction in interpreterir: 0x%x" , op )
}
c .pc ++
return nil
}
func (c *compiler ) nextFrameID () (id uint32 ) {
id = c .currentFrameID + 1
c .currentFrameID ++
return
}
func (c *compiler ) applyToStack (opcode wasm .Opcode ) (index uint32 , err error ) {
switch opcode {
case
wasm .OpcodeCall ,
wasm .OpcodeCallIndirect ,
wasm .OpcodeLocalGet ,
wasm .OpcodeLocalSet ,
wasm .OpcodeLocalTee ,
wasm .OpcodeGlobalGet ,
wasm .OpcodeGlobalSet :
v , num , err := leb128 .LoadUint32 (c .body [c .pc +1 :])
if err != nil {
return 0 , fmt .Errorf ("reading immediates: %w" , err )
}
c .pc += num
index = v
default :
}
if c .unreachableState .on {
return 0 , nil
}
s , err := c .wasmOpcodeSignature (opcode , index )
if err != nil {
return 0 , err
}
var typeParam unsignedType
var typeParamFound bool
for i := range s .in {
want := s .in [len (s .in )-1 -i ]
actual := c .stackPop ()
if want == unsignedTypeUnknown && typeParamFound {
want = typeParam
} else if want == unsignedTypeUnknown {
want = actual
typeParam = want
typeParamFound = true
}
if want != actual {
return 0 , fmt .Errorf ("input signature mismatch: want %s but have %s" , want , actual )
}
}
for _ , target := range s .out {
if target == unsignedTypeUnknown && !typeParamFound {
return 0 , fmt .Errorf ("cannot determine type of unknown result" )
} else if target == unsignedTypeUnknown {
c .stackPush (typeParam )
} else {
c .stackPush (target )
}
}
return index , nil
}
func (c *compiler ) stackPeek () (ret unsignedType ) {
ret = c .stack [len (c .stack )-1 ]
return
}
func (c *compiler ) stackSwitchAt (frame *controlFrame ) {
c .stack = c .stack [:frame .originalStackLenWithoutParam ]
c .stackLenInUint64 = frame .originalStackLenWithoutParamUint64
}
func (c *compiler ) stackPop () (ret unsignedType ) {
ret = c .stack [len (c .stack )-1 ]
c .stack = c .stack [:len (c .stack )-1 ]
c .stackLenInUint64 -= 1 + int (unsignedTypeV128 &ret >>2 )
return
}
func (c *compiler ) stackPush (ts unsignedType ) {
c .stack = append (c .stack , ts )
c .stackLenInUint64 += 1 + int (unsignedTypeV128 &ts >>2 )
}
func (c *compiler ) emit (op unionOperation ) {
if !c .unreachableState .on {
switch op .Kind {
case operationKindDrop :
if int64 (op .U1 ) == -1 {
return
}
}
c .result .Operations = append (c .result .Operations , op )
if c .needSourceOffset {
c .result .IROperationSourceOffsetsInWasmBinary = append (c .result .IROperationSourceOffsetsInWasmBinary ,
c .currentOpPC +c .bodyOffsetInCodeSection )
}
}
}
func (c *compiler ) emitDefaultValue (t wasm .ValueType ) {
switch t {
case wasm .ValueTypeI32 :
c .stackPush (unsignedTypeI32 )
c .emit (newOperationConstI32 (0 ))
case wasm .ValueTypeI64 , wasm .ValueTypeExternref , wasm .ValueTypeFuncref :
c .stackPush (unsignedTypeI64 )
c .emit (newOperationConstI64 (0 ))
case wasm .ValueTypeF32 :
c .stackPush (unsignedTypeF32 )
c .emit (newOperationConstF32 (0 ))
case wasm .ValueTypeF64 :
c .stackPush (unsignedTypeF64 )
c .emit (newOperationConstF64 (0 ))
case wasm .ValueTypeV128 :
c .stackPush (unsignedTypeV128 )
c .emit (newOperationV128Const (0 , 0 ))
}
}
func (c *compiler ) localDepth (index wasm .Index ) int {
height := c .localIndexToStackHeightInUint64 [index ]
return c .stackLenInUint64 - 1 - height
}
func (c *compiler ) localType (index wasm .Index ) (t wasm .ValueType ) {
if params := uint32 (len (c .sig .Params )); index < params {
t = c .sig .Params [index ]
} else {
t = c .localTypes [index -params ]
}
return
}
func (c *compiler ) getFrameDropRange (frame *controlFrame , isEnd bool ) inclusiveRange {
var start int
if !isEnd && frame .kind == controlFrameKindLoop {
start = frame .blockType .ParamNumInUint64
} else {
start = frame .blockType .ResultNumInUint64
}
end := c .stackLenInUint64 - 1 - frame .originalStackLenWithoutParamUint64
if start <= end {
return inclusiveRange {Start : int32 (start ), End : int32 (end )}
} else {
return nopinclusiveRange
}
}
func (c *compiler ) readMemoryArg (tag string ) (memoryArg , error ) {
c .result .UsesMemory = true
alignment , num , err := leb128 .LoadUint32 (c .body [c .pc +1 :])
if err != nil {
return memoryArg {}, fmt .Errorf ("reading alignment for %s: %w" , tag , err )
}
c .pc += num
offset , num , err := leb128 .LoadUint32 (c .body [c .pc +1 :])
if err != nil {
return memoryArg {}, fmt .Errorf ("reading offset for %s: %w" , tag , err )
}
c .pc += num
return memoryArg {Offset : offset , Alignment : alignment }, nil
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .