github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/internal/wazeroir/compiler.go (about)

     1  package wazeroir
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"fmt"
     7  	"math"
     8  	"strings"
     9  
    10  	"github.com/bananabytelabs/wazero/api"
    11  	"github.com/bananabytelabs/wazero/internal/leb128"
    12  	"github.com/bananabytelabs/wazero/internal/wasm"
    13  )
    14  
    15  type controlFrameKind byte
    16  
    17  const (
    18  	controlFrameKindBlockWithContinuationLabel controlFrameKind = iota
    19  	controlFrameKindBlockWithoutContinuationLabel
    20  	controlFrameKindFunction
    21  	controlFrameKindLoop
    22  	controlFrameKindIfWithElse
    23  	controlFrameKindIfWithoutElse
    24  )
    25  
    26  type (
    27  	controlFrame struct {
    28  		frameID uint32
    29  		// originalStackLen holds the number of values on the stack
    30  		// when Start executing this control frame minus params for the block.
    31  		originalStackLenWithoutParam int
    32  		blockType                    *wasm.FunctionType
    33  		kind                         controlFrameKind
    34  	}
    35  	controlFrames struct{ frames []controlFrame }
    36  )
    37  
    38  func (c *controlFrame) ensureContinuation() {
    39  	// Make sure that if the frame is block and doesn't have continuation,
    40  	// change the Kind so we can emit the continuation block
    41  	// later when we reach the End instruction of this frame.
    42  	if c.kind == controlFrameKindBlockWithoutContinuationLabel {
    43  		c.kind = controlFrameKindBlockWithContinuationLabel
    44  	}
    45  }
    46  
    47  func (c *controlFrame) asLabel() Label {
    48  	switch c.kind {
    49  	case controlFrameKindBlockWithContinuationLabel,
    50  		controlFrameKindBlockWithoutContinuationLabel:
    51  		return NewLabel(LabelKindContinuation, c.frameID)
    52  	case controlFrameKindLoop:
    53  		return NewLabel(LabelKindHeader, c.frameID)
    54  	case controlFrameKindFunction:
    55  		return NewLabel(LabelKindReturn, 0)
    56  	case controlFrameKindIfWithElse,
    57  		controlFrameKindIfWithoutElse:
    58  		return NewLabel(LabelKindContinuation, c.frameID)
    59  	}
    60  	panic(fmt.Sprintf("unreachable: a bug in wazeroir implementation: %v", c.kind))
    61  }
    62  
    63  func (c *controlFrames) functionFrame() *controlFrame {
    64  	// No need to check stack bound
    65  	// as we can assume that all the operations
    66  	// are valid thanks to validateFunction
    67  	// at module validation phase.
    68  	return &c.frames[0]
    69  }
    70  
    71  func (c *controlFrames) get(n int) *controlFrame {
    72  	// No need to check stack bound
    73  	// as we can assume that all the operations
    74  	// are valid thanks to validateFunction
    75  	// at module validation phase.
    76  	return &c.frames[len(c.frames)-n-1]
    77  }
    78  
    79  func (c *controlFrames) top() *controlFrame {
    80  	// No need to check stack bound
    81  	// as we can assume that all the operations
    82  	// are valid thanks to validateFunction
    83  	// at module validation phase.
    84  	return &c.frames[len(c.frames)-1]
    85  }
    86  
    87  func (c *controlFrames) empty() bool {
    88  	return len(c.frames) == 0
    89  }
    90  
    91  func (c *controlFrames) pop() (frame *controlFrame) {
    92  	// No need to check stack bound
    93  	// as we can assume that all the operations
    94  	// are valid thanks to validateFunction
    95  	// at module validation phase.
    96  	frame = c.top()
    97  	c.frames = c.frames[:len(c.frames)-1]
    98  	return
    99  }
   100  
   101  func (c *controlFrames) push(frame controlFrame) {
   102  	c.frames = append(c.frames, frame)
   103  }
   104  
   105  func (c *Compiler) initializeStack() {
   106  	// Reuse the existing slice.
   107  	c.localIndexToStackHeightInUint64 = c.localIndexToStackHeightInUint64[:0]
   108  	var current int
   109  	for _, lt := range c.sig.Params {
   110  		c.localIndexToStackHeightInUint64 = append(c.localIndexToStackHeightInUint64, current)
   111  		if lt == wasm.ValueTypeV128 {
   112  			current++
   113  		}
   114  		current++
   115  	}
   116  
   117  	if c.callFrameStackSizeInUint64 > 0 {
   118  		// We reserve the stack slots for result values below the return call frame slots.
   119  		if diff := c.sig.ResultNumInUint64 - c.sig.ParamNumInUint64; diff > 0 {
   120  			current += diff
   121  		}
   122  	}
   123  
   124  	// Non-func param locals Start after the return call frame.
   125  	current += c.callFrameStackSizeInUint64
   126  
   127  	for _, lt := range c.localTypes {
   128  		c.localIndexToStackHeightInUint64 = append(c.localIndexToStackHeightInUint64, current)
   129  		if lt == wasm.ValueTypeV128 {
   130  			current++
   131  		}
   132  		current++
   133  	}
   134  
   135  	// Push function arguments.
   136  	for _, t := range c.sig.Params {
   137  		c.stackPush(wasmValueTypeToUnsignedType(t))
   138  	}
   139  
   140  	if c.callFrameStackSizeInUint64 > 0 {
   141  		// Reserve the stack slots for results.
   142  		for i := 0; i < c.sig.ResultNumInUint64-c.sig.ParamNumInUint64; i++ {
   143  			c.stackPush(UnsignedTypeI64)
   144  		}
   145  
   146  		// Reserve the stack slots for call frame.
   147  		for i := 0; i < c.callFrameStackSizeInUint64; i++ {
   148  			c.stackPush(UnsignedTypeI64)
   149  		}
   150  	}
   151  }
   152  
   153  // Compiler is in charge of lowering raw Wasm function body to get CompilationResult.
   154  // This is created per *wasm.Module and reused for all functions in it to reduce memory allocations.
   155  type Compiler struct {
   156  	module                     *wasm.Module
   157  	enabledFeatures            api.CoreFeatures
   158  	callFrameStackSizeInUint64 int
   159  	stack                      []UnsignedType
   160  	currentFrameID             uint32
   161  	controlFrames              controlFrames
   162  	unreachableState           struct {
   163  		on    bool
   164  		depth int
   165  	}
   166  	pc, currentOpPC uint64
   167  	result          CompilationResult
   168  
   169  	// body holds the code for the function's body where Wasm instructions are stored.
   170  	body []byte
   171  	// sig is the function type of the target function.
   172  	sig *wasm.FunctionType
   173  	// localTypes holds the target function locals' value types except function params.
   174  	localTypes []wasm.ValueType
   175  	// localIndexToStackHeightInUint64 maps the local index (starting with function params) to the stack height
   176  	// where the local is places. This is the necessary mapping for functions who contain vector type locals.
   177  	localIndexToStackHeightInUint64 []int
   178  
   179  	// types hold all the function types in the module where the targe function exists.
   180  	types []wasm.FunctionType
   181  	// funcs holds the type indexes for all declared functions in the module where the target function exists.
   182  	funcs []uint32
   183  	// globals holds the global types for all declared globals in the module where the target function exists.
   184  	globals []wasm.GlobalType
   185  
   186  	// needSourceOffset is true if this module requires DWARF based stack trace.
   187  	needSourceOffset bool
   188  	// bodyOffsetInCodeSection is the offset of the body of this function in the original Wasm binary's code section.
   189  	bodyOffsetInCodeSection uint64
   190  
   191  	ensureTermination bool
   192  	// Pre-allocated bytes.Reader to be used in various places.
   193  	br             *bytes.Reader
   194  	funcTypeToSigs funcTypeToIRSignatures
   195  
   196  	next int
   197  }
   198  
   199  //lint:ignore U1000 for debugging only.
   200  func (c *Compiler) stackDump() string {
   201  	strs := make([]string, 0, len(c.stack))
   202  	for _, s := range c.stack {
   203  		strs = append(strs, s.String())
   204  	}
   205  	return "[" + strings.Join(strs, ", ") + "]"
   206  }
   207  
   208  func (c *Compiler) markUnreachable() {
   209  	c.unreachableState.on = true
   210  }
   211  
   212  func (c *Compiler) resetUnreachable() {
   213  	c.unreachableState.on = false
   214  }
   215  
   216  type CompilationResult struct {
   217  	// Operations holds wazeroir operations compiled from Wasm instructions in a Wasm function.
   218  	Operations []UnionOperation
   219  
   220  	// IROperationSourceOffsetsInWasmBinary is index-correlated with Operation and maps each operation to the corresponding source instruction's
   221  	// offset in the original WebAssembly binary.
   222  	// Non nil only when the given Wasm module has the DWARF section.
   223  	IROperationSourceOffsetsInWasmBinary []uint64
   224  
   225  	// LabelCallers maps Label to the number of callers to that label.
   226  	// Here "callers" means that the call-sites which jumps to the label with br, br_if or br_table
   227  	// instructions.
   228  	//
   229  	// Note: zero possible and allowed in wasm. e.g.
   230  	//
   231  	//	(block
   232  	//	  (br 0)
   233  	//	  (block i32.const 1111)
   234  	//	)
   235  	//
   236  	// This example the label corresponding to `(block i32.const 1111)` is never be reached at runtime because `br 0` exits the function before we reach there
   237  	LabelCallers map[Label]uint32
   238  	// UsesMemory is true if this function might use memory.
   239  	UsesMemory bool
   240  
   241  	// The following fields are per-module values, not per-function.
   242  
   243  	// Globals holds all the declarations of globals in the module from which this function is compiled.
   244  	Globals []wasm.GlobalType
   245  	// Functions holds all the declarations of function in the module from which this function is compiled, including itself.
   246  	Functions []wasm.Index
   247  	// Types holds all the types in the module from which this function is compiled.
   248  	Types []wasm.FunctionType
   249  	// HasMemory is true if the module from which this function is compiled has memory declaration.
   250  	HasMemory bool
   251  	// HasTable is true if the module from which this function is compiled has table declaration.
   252  	HasTable bool
   253  	// HasDataInstances is true if the module has data instances which might be used by memory.init or data.drop instructions.
   254  	HasDataInstances bool
   255  	// HasDataInstances is true if the module has element instances which might be used by table.init or elem.drop instructions.
   256  	HasElementInstances bool
   257  }
   258  
   259  // NewCompiler returns the new *Compiler for the given parameters.
   260  // Use Compiler.Next function to get compilation result per function.
   261  func NewCompiler(enabledFeatures api.CoreFeatures, callFrameStackSizeInUint64 int, module *wasm.Module, ensureTermination bool) (*Compiler, error) {
   262  	functions, globals, mem, tables, err := module.AllDeclarations()
   263  	if err != nil {
   264  		return nil, err
   265  	}
   266  
   267  	hasMemory, hasTable, hasDataInstances, hasElementInstances := mem != nil, len(tables) > 0,
   268  		len(module.DataSection) > 0, len(module.ElementSection) > 0
   269  
   270  	types := module.TypeSection
   271  
   272  	c := &Compiler{
   273  		module:                     module,
   274  		enabledFeatures:            enabledFeatures,
   275  		controlFrames:              controlFrames{},
   276  		callFrameStackSizeInUint64: callFrameStackSizeInUint64,
   277  		result: CompilationResult{
   278  			Globals:             globals,
   279  			Functions:           functions,
   280  			Types:               types,
   281  			HasMemory:           hasMemory,
   282  			HasTable:            hasTable,
   283  			HasDataInstances:    hasDataInstances,
   284  			HasElementInstances: hasElementInstances,
   285  			LabelCallers:        map[Label]uint32{},
   286  		},
   287  		globals:           globals,
   288  		funcs:             functions,
   289  		types:             types,
   290  		ensureTermination: ensureTermination,
   291  		br:                bytes.NewReader(nil),
   292  		funcTypeToSigs: funcTypeToIRSignatures{
   293  			indirectCalls: make([]*signature, len(types)),
   294  			directCalls:   make([]*signature, len(types)),
   295  			wasmTypes:     types,
   296  		},
   297  		needSourceOffset: module.DWARFLines != nil,
   298  	}
   299  	return c, nil
   300  }
   301  
   302  // Next returns the next CompilationResult for this Compiler.
   303  func (c *Compiler) Next() (*CompilationResult, error) {
   304  	funcIndex := c.next
   305  	code := &c.module.CodeSection[funcIndex]
   306  	sig := &c.types[c.module.FunctionSection[funcIndex]]
   307  
   308  	// Reset the previous result.
   309  	c.result.Operations = c.result.Operations[:0]
   310  	c.result.IROperationSourceOffsetsInWasmBinary = c.result.IROperationSourceOffsetsInWasmBinary[:0]
   311  	c.result.UsesMemory = false
   312  	// Clears the existing entries in LabelCallers.
   313  	for frameID := uint32(0); frameID <= c.currentFrameID; frameID++ {
   314  		for k := LabelKind(0); k < LabelKindNum; k++ {
   315  			delete(c.result.LabelCallers, NewLabel(k, frameID))
   316  		}
   317  	}
   318  	// Reset the previous states.
   319  	c.pc = 0
   320  	c.currentOpPC = 0
   321  	c.currentFrameID = 0
   322  	c.unreachableState.on, c.unreachableState.depth = false, 0
   323  
   324  	if err := c.compile(sig, code.Body, code.LocalTypes, code.BodyOffsetInCodeSection); err != nil {
   325  		return nil, err
   326  	}
   327  	c.next++
   328  	return &c.result, nil
   329  }
   330  
   331  // Compile lowers given function instance into wazeroir operations
   332  // so that the resulting operations can be consumed by the interpreter
   333  // or the Compiler compilation engine.
   334  func (c *Compiler) compile(sig *wasm.FunctionType, body []byte, localTypes []wasm.ValueType, bodyOffsetInCodeSection uint64) error {
   335  	// Set function specific fields.
   336  	c.body = body
   337  	c.localTypes = localTypes
   338  	c.sig = sig
   339  	c.bodyOffsetInCodeSection = bodyOffsetInCodeSection
   340  
   341  	// Reuses the underlying slices.
   342  	c.stack = c.stack[:0]
   343  	c.controlFrames.frames = c.controlFrames.frames[:0]
   344  
   345  	c.initializeStack()
   346  
   347  	// Emit const expressions for locals.
   348  	// Note that here we don't take function arguments
   349  	// into account, meaning that callers must push
   350  	// arguments before entering into the function body.
   351  	for _, t := range c.localTypes {
   352  		c.emitDefaultValue(t)
   353  	}
   354  
   355  	// Insert the function control frame.
   356  	c.controlFrames.push(controlFrame{
   357  		frameID:   c.nextFrameID(),
   358  		blockType: c.sig,
   359  		kind:      controlFrameKindFunction,
   360  	})
   361  
   362  	// Now, enter the function body.
   363  	for !c.controlFrames.empty() && c.pc < uint64(len(c.body)) {
   364  		if err := c.handleInstruction(); err != nil {
   365  			return fmt.Errorf("handling instruction: %w", err)
   366  		}
   367  	}
   368  	return nil
   369  }
   370  
   371  // Translate the current Wasm instruction to wazeroir's operations,
   372  // and emit the results into c.results.
   373  func (c *Compiler) handleInstruction() error {
   374  	op := c.body[c.pc]
   375  	c.currentOpPC = c.pc
   376  	if false {
   377  		var instName string
   378  		if op == wasm.OpcodeVecPrefix {
   379  			instName = wasm.VectorInstructionName(c.body[c.pc+1])
   380  		} else if op == wasm.OpcodeAtomicPrefix {
   381  			instName = wasm.AtomicInstructionName(c.body[c.pc+1])
   382  		} else if op == wasm.OpcodeMiscPrefix {
   383  			instName = wasm.MiscInstructionName(c.body[c.pc+1])
   384  		} else {
   385  			instName = wasm.InstructionName(op)
   386  		}
   387  		fmt.Printf("handling %s, unreachable_state(on=%v,depth=%d), stack=%v\n",
   388  			instName, c.unreachableState.on, c.unreachableState.depth, c.stack,
   389  		)
   390  	}
   391  
   392  	var peekValueType UnsignedType
   393  	if len(c.stack) > 0 {
   394  		peekValueType = c.stackPeek()
   395  	}
   396  
   397  	// Modify the stack according the current instruction.
   398  	// Note that some instructions will read "index" in
   399  	// applyToStack and advance c.pc inside the function.
   400  	index, err := c.applyToStack(op)
   401  	if err != nil {
   402  		return fmt.Errorf("apply stack failed for %s: %w", wasm.InstructionName(op), err)
   403  	}
   404  	// Now we handle each instruction, and
   405  	// emit the corresponding wazeroir operations to the results.
   406  operatorSwitch:
   407  	switch op {
   408  	case wasm.OpcodeUnreachable:
   409  		c.emit(NewOperationUnreachable())
   410  		c.markUnreachable()
   411  	case wasm.OpcodeNop:
   412  		// Nop is noop!
   413  	case wasm.OpcodeBlock:
   414  		c.br.Reset(c.body[c.pc+1:])
   415  		bt, num, err := wasm.DecodeBlockType(c.types, c.br, c.enabledFeatures)
   416  		if err != nil {
   417  			return fmt.Errorf("reading block type for block instruction: %w", err)
   418  		}
   419  		c.pc += num
   420  
   421  		if c.unreachableState.on {
   422  			// If it is currently in unreachable,
   423  			// just remove the entire block.
   424  			c.unreachableState.depth++
   425  			break operatorSwitch
   426  		}
   427  
   428  		// Create a new frame -- entering this block.
   429  		frame := controlFrame{
   430  			frameID:                      c.nextFrameID(),
   431  			originalStackLenWithoutParam: len(c.stack) - len(bt.Params),
   432  			kind:                         controlFrameKindBlockWithoutContinuationLabel,
   433  			blockType:                    bt,
   434  		}
   435  		c.controlFrames.push(frame)
   436  
   437  	case wasm.OpcodeLoop:
   438  		c.br.Reset(c.body[c.pc+1:])
   439  		bt, num, err := wasm.DecodeBlockType(c.types, c.br, c.enabledFeatures)
   440  		if err != nil {
   441  			return fmt.Errorf("reading block type for loop instruction: %w", err)
   442  		}
   443  		c.pc += num
   444  
   445  		if c.unreachableState.on {
   446  			// If it is currently in unreachable,
   447  			// just remove the entire block.
   448  			c.unreachableState.depth++
   449  			break operatorSwitch
   450  		}
   451  
   452  		// Create a new frame -- entering loop.
   453  		frame := controlFrame{
   454  			frameID:                      c.nextFrameID(),
   455  			originalStackLenWithoutParam: len(c.stack) - len(bt.Params),
   456  			kind:                         controlFrameKindLoop,
   457  			blockType:                    bt,
   458  		}
   459  		c.controlFrames.push(frame)
   460  
   461  		// Prep labels for inside and the continuation of this loop.
   462  		loopLabel := NewLabel(LabelKindHeader, frame.frameID)
   463  		c.result.LabelCallers[loopLabel]++
   464  
   465  		// Emit the branch operation to enter inside the loop.
   466  		c.emit(NewOperationBr(loopLabel))
   467  		c.emit(NewOperationLabel(loopLabel))
   468  
   469  		// Insert the exit code check on the loop header, which is the only necessary point in the function body
   470  		// to prevent infinite loop.
   471  		//
   472  		// Note that this is a little aggressive: this checks the exit code regardless the loop header is actually
   473  		// the loop. In other words, this checks even when no br/br_if/br_table instructions jumping to this loop
   474  		// exist. However, in reality, that shouldn't be an issue since such "noop" loop header will highly likely be
   475  		// optimized out by almost all guest language compilers which have the control flow optimization passes.
   476  		if c.ensureTermination {
   477  			c.emit(NewOperationBuiltinFunctionCheckExitCode())
   478  		}
   479  	case wasm.OpcodeIf:
   480  		c.br.Reset(c.body[c.pc+1:])
   481  		bt, num, err := wasm.DecodeBlockType(c.types, c.br, c.enabledFeatures)
   482  		if err != nil {
   483  			return fmt.Errorf("reading block type for if instruction: %w", err)
   484  		}
   485  		c.pc += num
   486  
   487  		if c.unreachableState.on {
   488  			// If it is currently in unreachable,
   489  			// just remove the entire block.
   490  			c.unreachableState.depth++
   491  			break operatorSwitch
   492  		}
   493  
   494  		// Create a new frame -- entering if.
   495  		frame := controlFrame{
   496  			frameID:                      c.nextFrameID(),
   497  			originalStackLenWithoutParam: len(c.stack) - len(bt.Params),
   498  			// Note this will be set to controlFrameKindIfWithElse
   499  			// when else opcode found later.
   500  			kind:      controlFrameKindIfWithoutElse,
   501  			blockType: bt,
   502  		}
   503  		c.controlFrames.push(frame)
   504  
   505  		// Prep labels for if and else of this if.
   506  		thenLabel := NewLabel(LabelKindHeader, frame.frameID)
   507  		elseLabel := NewLabel(LabelKindElse, frame.frameID)
   508  		c.result.LabelCallers[thenLabel]++
   509  		c.result.LabelCallers[elseLabel]++
   510  
   511  		// Emit the branch operation to enter the then block.
   512  		c.emit(NewOperationBrIf(thenLabel, elseLabel, NopInclusiveRange))
   513  		c.emit(NewOperationLabel(thenLabel))
   514  	case wasm.OpcodeElse:
   515  		frame := c.controlFrames.top()
   516  		if c.unreachableState.on && c.unreachableState.depth > 0 {
   517  			// If it is currently in unreachable, and the nested if,
   518  			// just remove the entire else block.
   519  			break operatorSwitch
   520  		} else if c.unreachableState.on {
   521  			// If it is currently in unreachable, and the non-nested if,
   522  			// reset the stack so we can correctly handle the else block.
   523  			top := c.controlFrames.top()
   524  			c.stack = c.stack[:top.originalStackLenWithoutParam]
   525  			top.kind = controlFrameKindIfWithElse
   526  
   527  			// Re-push the parameters to the if block so that else block can use them.
   528  			for _, t := range frame.blockType.Params {
   529  				c.stackPush(wasmValueTypeToUnsignedType(t))
   530  			}
   531  
   532  			// We are no longer unreachable in else frame,
   533  			// so emit the correct label, and reset the unreachable state.
   534  			elseLabel := NewLabel(LabelKindElse, frame.frameID)
   535  			c.resetUnreachable()
   536  			c.emit(
   537  				NewOperationLabel(elseLabel),
   538  			)
   539  			break operatorSwitch
   540  		}
   541  
   542  		// Change the Kind of this If block, indicating that
   543  		// the if has else block.
   544  		frame.kind = controlFrameKindIfWithElse
   545  
   546  		// We need to reset the stack so that
   547  		// the values pushed inside the then block
   548  		// do not affect the else block.
   549  		dropOp := NewOperationDrop(c.getFrameDropRange(frame, false))
   550  
   551  		// Reset the stack manipulated by the then block, and re-push the block param types to the stack.
   552  
   553  		c.stack = c.stack[:frame.originalStackLenWithoutParam]
   554  		for _, t := range frame.blockType.Params {
   555  			c.stackPush(wasmValueTypeToUnsignedType(t))
   556  		}
   557  
   558  		// Prep labels for else and the continuation of this if block.
   559  		elseLabel := NewLabel(LabelKindElse, frame.frameID)
   560  		continuationLabel := NewLabel(LabelKindContinuation, frame.frameID)
   561  		c.result.LabelCallers[continuationLabel]++
   562  
   563  		// Emit the instructions for exiting the if loop,
   564  		// and then the initiation of else block.
   565  		c.emit(dropOp)
   566  		// Jump to the continuation of this block.
   567  		c.emit(NewOperationBr(continuationLabel))
   568  		// Initiate the else block.
   569  		c.emit(NewOperationLabel(elseLabel))
   570  	case wasm.OpcodeEnd:
   571  		if c.unreachableState.on && c.unreachableState.depth > 0 {
   572  			c.unreachableState.depth--
   573  			break operatorSwitch
   574  		} else if c.unreachableState.on {
   575  			c.resetUnreachable()
   576  
   577  			frame := c.controlFrames.pop()
   578  			if c.controlFrames.empty() {
   579  				return nil
   580  			}
   581  
   582  			c.stack = c.stack[:frame.originalStackLenWithoutParam]
   583  			for _, t := range frame.blockType.Results {
   584  				c.stackPush(wasmValueTypeToUnsignedType(t))
   585  			}
   586  
   587  			continuationLabel := NewLabel(LabelKindContinuation, frame.frameID)
   588  			if frame.kind == controlFrameKindIfWithoutElse {
   589  				// Emit the else label.
   590  				elseLabel := NewLabel(LabelKindElse, frame.frameID)
   591  				c.result.LabelCallers[continuationLabel]++
   592  				c.emit(NewOperationLabel(elseLabel))
   593  				c.emit(NewOperationBr(continuationLabel))
   594  				c.emit(NewOperationLabel(continuationLabel))
   595  			} else {
   596  				c.emit(
   597  					NewOperationLabel(continuationLabel),
   598  				)
   599  			}
   600  
   601  			break operatorSwitch
   602  		}
   603  
   604  		frame := c.controlFrames.pop()
   605  
   606  		// We need to reset the stack so that
   607  		// the values pushed inside the block.
   608  		dropOp := NewOperationDrop(c.getFrameDropRange(frame, true))
   609  		c.stack = c.stack[:frame.originalStackLenWithoutParam]
   610  
   611  		// Push the result types onto the stack.
   612  		for _, t := range frame.blockType.Results {
   613  			c.stackPush(wasmValueTypeToUnsignedType(t))
   614  		}
   615  
   616  		// Emit the instructions according to the Kind of the current control frame.
   617  		switch frame.kind {
   618  		case controlFrameKindFunction:
   619  			if !c.controlFrames.empty() {
   620  				// Should never happen. If so, there's a bug in the translation.
   621  				panic("bug: found more function control frames")
   622  			}
   623  			// Return from function.
   624  			c.emit(dropOp)
   625  			c.emit(NewOperationBr(NewLabel(LabelKindReturn, 0)))
   626  		case controlFrameKindIfWithoutElse:
   627  			// This case we have to emit "empty" else label.
   628  			elseLabel := NewLabel(LabelKindElse, frame.frameID)
   629  			continuationLabel := NewLabel(LabelKindContinuation, frame.frameID)
   630  			c.result.LabelCallers[continuationLabel] += 2
   631  			c.emit(dropOp)
   632  			c.emit(NewOperationBr(continuationLabel))
   633  			// Emit the else which soon branches into the continuation.
   634  			c.emit(NewOperationLabel(elseLabel))
   635  			c.emit(NewOperationBr(continuationLabel))
   636  			// Initiate the continuation.
   637  			c.emit(NewOperationLabel(continuationLabel))
   638  		case controlFrameKindBlockWithContinuationLabel,
   639  			controlFrameKindIfWithElse:
   640  			continuationLabel := NewLabel(LabelKindContinuation, frame.frameID)
   641  			c.result.LabelCallers[continuationLabel]++
   642  			c.emit(dropOp)
   643  			c.emit(NewOperationBr(continuationLabel))
   644  			c.emit(NewOperationLabel(continuationLabel))
   645  		case controlFrameKindLoop, controlFrameKindBlockWithoutContinuationLabel:
   646  			c.emit(
   647  				dropOp,
   648  			)
   649  		default:
   650  			// Should never happen. If so, there's a bug in the translation.
   651  			panic(fmt.Errorf("bug: invalid control frame Kind: 0x%x", frame.kind))
   652  		}
   653  
   654  	case wasm.OpcodeBr:
   655  		targetIndex, n, err := leb128.LoadUint32(c.body[c.pc+1:])
   656  		if err != nil {
   657  			return fmt.Errorf("read the target for br_if: %w", err)
   658  		}
   659  		c.pc += n
   660  
   661  		if c.unreachableState.on {
   662  			// If it is currently in unreachable, br is no-op.
   663  			break operatorSwitch
   664  		}
   665  
   666  		targetFrame := c.controlFrames.get(int(targetIndex))
   667  		targetFrame.ensureContinuation()
   668  		dropOp := NewOperationDrop(c.getFrameDropRange(targetFrame, false))
   669  		targetID := targetFrame.asLabel()
   670  		c.result.LabelCallers[targetID]++
   671  		c.emit(dropOp)
   672  		c.emit(NewOperationBr(targetID))
   673  		// Br operation is stack-polymorphic, and mark the state as unreachable.
   674  		// That means subsequent instructions in the current control frame are "unreachable"
   675  		// and can be safely removed.
   676  		c.markUnreachable()
   677  	case wasm.OpcodeBrIf:
   678  		targetIndex, n, err := leb128.LoadUint32(c.body[c.pc+1:])
   679  		if err != nil {
   680  			return fmt.Errorf("read the target for br_if: %w", err)
   681  		}
   682  		c.pc += n
   683  
   684  		if c.unreachableState.on {
   685  			// If it is currently in unreachable, br-if is no-op.
   686  			break operatorSwitch
   687  		}
   688  
   689  		targetFrame := c.controlFrames.get(int(targetIndex))
   690  		targetFrame.ensureContinuation()
   691  		drop := c.getFrameDropRange(targetFrame, false)
   692  		target := targetFrame.asLabel()
   693  		c.result.LabelCallers[target]++
   694  
   695  		continuationLabel := NewLabel(LabelKindHeader, c.nextFrameID())
   696  		c.result.LabelCallers[continuationLabel]++
   697  		c.emit(NewOperationBrIf(target, continuationLabel, drop))
   698  		// Start emitting else block operations.
   699  		c.emit(NewOperationLabel(continuationLabel))
   700  	case wasm.OpcodeBrTable:
   701  		c.br.Reset(c.body[c.pc+1:])
   702  		r := c.br
   703  		numTargets, n, err := leb128.DecodeUint32(r)
   704  		if err != nil {
   705  			return fmt.Errorf("error reading number of targets in br_table: %w", err)
   706  		}
   707  		c.pc += n
   708  
   709  		if c.unreachableState.on {
   710  			// If it is currently in unreachable, br_table is no-op.
   711  			// But before proceeding to the next instruction, we must advance the pc
   712  			// according to the number of br_table targets.
   713  			for i := uint32(0); i <= numTargets; i++ { // inclusive as we also need to read the index of default target.
   714  				_, n, err := leb128.DecodeUint32(r)
   715  				if err != nil {
   716  					return fmt.Errorf("error reading target %d in br_table: %w", i, err)
   717  				}
   718  				c.pc += n
   719  			}
   720  			break operatorSwitch
   721  		}
   722  
   723  		// Read the branch targets.
   724  		s := numTargets * 2
   725  		targetLabels := make([]uint64, 2+s) // (label, InclusiveRange) * (default+numTargets)
   726  		for i := uint32(0); i < s; i += 2 {
   727  			l, n, err := leb128.DecodeUint32(r)
   728  			if err != nil {
   729  				return fmt.Errorf("error reading target %d in br_table: %w", i, err)
   730  			}
   731  			c.pc += n
   732  			targetFrame := c.controlFrames.get(int(l))
   733  			targetFrame.ensureContinuation()
   734  			drop := c.getFrameDropRange(targetFrame, false)
   735  			targetLabel := targetFrame.asLabel()
   736  			targetLabels[i] = uint64(targetLabel)
   737  			targetLabels[i+1] = drop.AsU64()
   738  			c.result.LabelCallers[targetLabel]++
   739  		}
   740  
   741  		// Prep default target control frame.
   742  		l, n, err := leb128.DecodeUint32(r)
   743  		if err != nil {
   744  			return fmt.Errorf("error reading default target of br_table: %w", err)
   745  		}
   746  		c.pc += n
   747  		defaultTargetFrame := c.controlFrames.get(int(l))
   748  		defaultTargetFrame.ensureContinuation()
   749  		defaultTargetDrop := c.getFrameDropRange(defaultTargetFrame, false)
   750  		defaultLabel := defaultTargetFrame.asLabel()
   751  		c.result.LabelCallers[defaultLabel]++
   752  		targetLabels[s] = uint64(defaultLabel)
   753  		targetLabels[s+1] = defaultTargetDrop.AsU64()
   754  		c.emit(NewOperationBrTable(targetLabels))
   755  
   756  		// br_table operation is stack-polymorphic, and mark the state as unreachable.
   757  		// That means subsequent instructions in the current control frame are "unreachable"
   758  		// and can be safely removed.
   759  		c.markUnreachable()
   760  	case wasm.OpcodeReturn:
   761  		functionFrame := c.controlFrames.functionFrame()
   762  		dropOp := NewOperationDrop(c.getFrameDropRange(functionFrame, false))
   763  
   764  		// Cleanup the stack and then jmp to function frame's continuation (meaning return).
   765  		c.emit(dropOp)
   766  		c.emit(NewOperationBr(functionFrame.asLabel()))
   767  
   768  		// Return operation is stack-polymorphic, and mark the state as unreachable.
   769  		// That means subsequent instructions in the current control frame are "unreachable"
   770  		// and can be safely removed.
   771  		c.markUnreachable()
   772  	case wasm.OpcodeCall:
   773  		c.emit(
   774  			NewOperationCall(index),
   775  		)
   776  	case wasm.OpcodeCallIndirect:
   777  		typeIndex := index
   778  		tableIndex, n, err := leb128.LoadUint32(c.body[c.pc+1:])
   779  		if err != nil {
   780  			return fmt.Errorf("read target for br_table: %w", err)
   781  		}
   782  		c.pc += n
   783  		c.emit(
   784  			NewOperationCallIndirect(typeIndex, tableIndex),
   785  		)
   786  	case wasm.OpcodeDrop:
   787  		r := InclusiveRange{Start: 0, End: 0}
   788  		if peekValueType == UnsignedTypeV128 {
   789  			// InclusiveRange is the range in uint64 representation, so dropping a vector value on top
   790  			// should be translated as drop [0..1] inclusively.
   791  			r.End++
   792  		}
   793  		c.emit(NewOperationDrop(r))
   794  	case wasm.OpcodeSelect:
   795  		// If it is on the unreachable state, ignore the instruction.
   796  		if c.unreachableState.on {
   797  			break operatorSwitch
   798  		}
   799  		isTargetVector := c.stackPeek() == UnsignedTypeV128
   800  		c.emit(
   801  			NewOperationSelect(isTargetVector),
   802  		)
   803  	case wasm.OpcodeTypedSelect:
   804  		// Skips two bytes: vector size fixed to 1, and the value type for select.
   805  		c.pc += 2
   806  		// If it is on the unreachable state, ignore the instruction.
   807  		if c.unreachableState.on {
   808  			break operatorSwitch
   809  		}
   810  		// Typed select is semantically equivalent to select at runtime.
   811  		isTargetVector := c.stackPeek() == UnsignedTypeV128
   812  		c.emit(
   813  			NewOperationSelect(isTargetVector),
   814  		)
   815  	case wasm.OpcodeLocalGet:
   816  		depth := c.localDepth(index)
   817  		if isVector := c.localType(index) == wasm.ValueTypeV128; !isVector {
   818  			c.emit(
   819  				// -1 because we already manipulated the stack before
   820  				// called localDepth ^^.
   821  				NewOperationPick(depth-1, isVector),
   822  			)
   823  		} else {
   824  			c.emit(
   825  				// -2 because we already manipulated the stack before
   826  				// called localDepth ^^.
   827  				NewOperationPick(depth-2, isVector),
   828  			)
   829  		}
   830  	case wasm.OpcodeLocalSet:
   831  		depth := c.localDepth(index)
   832  
   833  		isVector := c.localType(index) == wasm.ValueTypeV128
   834  		if isVector {
   835  			c.emit(
   836  				// +2 because we already popped the operands for this operation from the c.stack before
   837  				// called localDepth ^^,
   838  				NewOperationSet(depth+2, isVector),
   839  			)
   840  		} else {
   841  			c.emit(
   842  				// +1 because we already popped the operands for this operation from the c.stack before
   843  				// called localDepth ^^,
   844  				NewOperationSet(depth+1, isVector),
   845  			)
   846  		}
   847  	case wasm.OpcodeLocalTee:
   848  		depth := c.localDepth(index)
   849  		isVector := c.localType(index) == wasm.ValueTypeV128
   850  		if isVector {
   851  			c.emit(NewOperationPick(1, isVector))
   852  			c.emit(NewOperationSet(depth+2, isVector))
   853  		} else {
   854  			c.emit(
   855  				NewOperationPick(0, isVector))
   856  			c.emit(NewOperationSet(depth+1, isVector))
   857  		}
   858  	case wasm.OpcodeGlobalGet:
   859  		c.emit(
   860  			NewOperationGlobalGet(index),
   861  		)
   862  	case wasm.OpcodeGlobalSet:
   863  		c.emit(
   864  			NewOperationGlobalSet(index),
   865  		)
   866  	case wasm.OpcodeI32Load:
   867  		imm, err := c.readMemoryArg(wasm.OpcodeI32LoadName)
   868  		if err != nil {
   869  			return err
   870  		}
   871  		c.emit(NewOperationLoad(UnsignedTypeI32, imm))
   872  	case wasm.OpcodeI64Load:
   873  		imm, err := c.readMemoryArg(wasm.OpcodeI64LoadName)
   874  		if err != nil {
   875  			return err
   876  		}
   877  		c.emit(NewOperationLoad(UnsignedTypeI64, imm))
   878  	case wasm.OpcodeF32Load:
   879  		imm, err := c.readMemoryArg(wasm.OpcodeF32LoadName)
   880  		if err != nil {
   881  			return err
   882  		}
   883  		c.emit(NewOperationLoad(UnsignedTypeF32, imm))
   884  	case wasm.OpcodeF64Load:
   885  		imm, err := c.readMemoryArg(wasm.OpcodeF64LoadName)
   886  		if err != nil {
   887  			return err
   888  		}
   889  		c.emit(NewOperationLoad(UnsignedTypeF64, imm))
   890  	case wasm.OpcodeI32Load8S:
   891  		imm, err := c.readMemoryArg(wasm.OpcodeI32Load8SName)
   892  		if err != nil {
   893  			return err
   894  		}
   895  		c.emit(NewOperationLoad8(SignedInt32, imm))
   896  	case wasm.OpcodeI32Load8U:
   897  		imm, err := c.readMemoryArg(wasm.OpcodeI32Load8UName)
   898  		if err != nil {
   899  			return err
   900  		}
   901  		c.emit(NewOperationLoad8(SignedUint32, imm))
   902  	case wasm.OpcodeI32Load16S:
   903  		imm, err := c.readMemoryArg(wasm.OpcodeI32Load16SName)
   904  		if err != nil {
   905  			return err
   906  		}
   907  		c.emit(NewOperationLoad16(SignedInt32, imm))
   908  	case wasm.OpcodeI32Load16U:
   909  		imm, err := c.readMemoryArg(wasm.OpcodeI32Load16UName)
   910  		if err != nil {
   911  			return err
   912  		}
   913  		c.emit(NewOperationLoad16(SignedUint32, imm))
   914  	case wasm.OpcodeI64Load8S:
   915  		imm, err := c.readMemoryArg(wasm.OpcodeI64Load8SName)
   916  		if err != nil {
   917  			return err
   918  		}
   919  		c.emit(NewOperationLoad8(SignedInt64, imm))
   920  	case wasm.OpcodeI64Load8U:
   921  		imm, err := c.readMemoryArg(wasm.OpcodeI64Load8UName)
   922  		if err != nil {
   923  			return err
   924  		}
   925  		c.emit(NewOperationLoad8(SignedUint64, imm))
   926  	case wasm.OpcodeI64Load16S:
   927  		imm, err := c.readMemoryArg(wasm.OpcodeI64Load16SName)
   928  		if err != nil {
   929  			return err
   930  		}
   931  		c.emit(NewOperationLoad16(SignedInt64, imm))
   932  	case wasm.OpcodeI64Load16U:
   933  		imm, err := c.readMemoryArg(wasm.OpcodeI64Load16UName)
   934  		if err != nil {
   935  			return err
   936  		}
   937  		c.emit(NewOperationLoad16(SignedUint64, imm))
   938  	case wasm.OpcodeI64Load32S:
   939  		imm, err := c.readMemoryArg(wasm.OpcodeI64Load32SName)
   940  		if err != nil {
   941  			return err
   942  		}
   943  		c.emit(NewOperationLoad32(true, imm))
   944  	case wasm.OpcodeI64Load32U:
   945  		imm, err := c.readMemoryArg(wasm.OpcodeI64Load32UName)
   946  		if err != nil {
   947  			return err
   948  		}
   949  		c.emit(NewOperationLoad32(false, imm))
   950  	case wasm.OpcodeI32Store:
   951  		imm, err := c.readMemoryArg(wasm.OpcodeI32StoreName)
   952  		if err != nil {
   953  			return err
   954  		}
   955  		c.emit(
   956  			NewOperationStore(UnsignedTypeI32, imm),
   957  		)
   958  	case wasm.OpcodeI64Store:
   959  		imm, err := c.readMemoryArg(wasm.OpcodeI64StoreName)
   960  		if err != nil {
   961  			return err
   962  		}
   963  		c.emit(
   964  			NewOperationStore(UnsignedTypeI64, imm),
   965  		)
   966  	case wasm.OpcodeF32Store:
   967  		imm, err := c.readMemoryArg(wasm.OpcodeF32StoreName)
   968  		if err != nil {
   969  			return err
   970  		}
   971  		c.emit(
   972  			NewOperationStore(UnsignedTypeF32, imm),
   973  		)
   974  	case wasm.OpcodeF64Store:
   975  		imm, err := c.readMemoryArg(wasm.OpcodeF64StoreName)
   976  		if err != nil {
   977  			return err
   978  		}
   979  		c.emit(
   980  			NewOperationStore(UnsignedTypeF64, imm),
   981  		)
   982  	case wasm.OpcodeI32Store8:
   983  		imm, err := c.readMemoryArg(wasm.OpcodeI32Store8Name)
   984  		if err != nil {
   985  			return err
   986  		}
   987  		c.emit(
   988  			NewOperationStore8(imm),
   989  		)
   990  	case wasm.OpcodeI32Store16:
   991  		imm, err := c.readMemoryArg(wasm.OpcodeI32Store16Name)
   992  		if err != nil {
   993  			return err
   994  		}
   995  		c.emit(
   996  			NewOperationStore16(imm),
   997  		)
   998  	case wasm.OpcodeI64Store8:
   999  		imm, err := c.readMemoryArg(wasm.OpcodeI64Store8Name)
  1000  		if err != nil {
  1001  			return err
  1002  		}
  1003  		c.emit(
  1004  			NewOperationStore8(imm),
  1005  		)
  1006  	case wasm.OpcodeI64Store16:
  1007  		imm, err := c.readMemoryArg(wasm.OpcodeI64Store16Name)
  1008  		if err != nil {
  1009  			return err
  1010  		}
  1011  		c.emit(
  1012  			NewOperationStore16(imm),
  1013  		)
  1014  	case wasm.OpcodeI64Store32:
  1015  		imm, err := c.readMemoryArg(wasm.OpcodeI64Store32Name)
  1016  		if err != nil {
  1017  			return err
  1018  		}
  1019  		c.emit(
  1020  			NewOperationStore32(imm),
  1021  		)
  1022  	case wasm.OpcodeMemorySize:
  1023  		c.result.UsesMemory = true
  1024  		c.pc++ // Skip the reserved one byte.
  1025  		c.emit(
  1026  			NewOperationMemorySize(),
  1027  		)
  1028  	case wasm.OpcodeMemoryGrow:
  1029  		c.result.UsesMemory = true
  1030  		c.pc++ // Skip the reserved one byte.
  1031  		c.emit(
  1032  			NewOperationMemoryGrow(),
  1033  		)
  1034  	case wasm.OpcodeI32Const:
  1035  		val, num, err := leb128.LoadInt32(c.body[c.pc+1:])
  1036  		if err != nil {
  1037  			return fmt.Errorf("reading i32.const value: %v", err)
  1038  		}
  1039  		c.pc += num
  1040  		c.emit(
  1041  			NewOperationConstI32(uint32(val)),
  1042  		)
  1043  	case wasm.OpcodeI64Const:
  1044  		val, num, err := leb128.LoadInt64(c.body[c.pc+1:])
  1045  		if err != nil {
  1046  			return fmt.Errorf("reading i64.const value: %v", err)
  1047  		}
  1048  		c.pc += num
  1049  		c.emit(
  1050  			NewOperationConstI64(uint64(val)),
  1051  		)
  1052  	case wasm.OpcodeF32Const:
  1053  		v := math.Float32frombits(binary.LittleEndian.Uint32(c.body[c.pc+1:]))
  1054  		c.pc += 4
  1055  		c.emit(
  1056  			NewOperationConstF32(v),
  1057  		)
  1058  	case wasm.OpcodeF64Const:
  1059  		v := math.Float64frombits(binary.LittleEndian.Uint64(c.body[c.pc+1:]))
  1060  		c.pc += 8
  1061  		c.emit(
  1062  			NewOperationConstF64(v),
  1063  		)
  1064  	case wasm.OpcodeI32Eqz:
  1065  		c.emit(
  1066  			NewOperationEqz(UnsignedInt32),
  1067  		)
  1068  	case wasm.OpcodeI32Eq:
  1069  		c.emit(
  1070  			NewOperationEq(UnsignedTypeI32),
  1071  		)
  1072  	case wasm.OpcodeI32Ne:
  1073  		c.emit(
  1074  			NewOperationNe(UnsignedTypeI32),
  1075  		)
  1076  	case wasm.OpcodeI32LtS:
  1077  		c.emit(
  1078  			NewOperationLt(SignedTypeInt32),
  1079  		)
  1080  	case wasm.OpcodeI32LtU:
  1081  		c.emit(
  1082  			NewOperationLt(SignedTypeUint32),
  1083  		)
  1084  	case wasm.OpcodeI32GtS:
  1085  		c.emit(
  1086  			NewOperationGt(SignedTypeInt32),
  1087  		)
  1088  	case wasm.OpcodeI32GtU:
  1089  		c.emit(
  1090  			NewOperationGt(SignedTypeUint32),
  1091  		)
  1092  	case wasm.OpcodeI32LeS:
  1093  		c.emit(
  1094  			NewOperationLe(SignedTypeInt32),
  1095  		)
  1096  	case wasm.OpcodeI32LeU:
  1097  		c.emit(
  1098  			NewOperationLe(SignedTypeUint32),
  1099  		)
  1100  	case wasm.OpcodeI32GeS:
  1101  		c.emit(
  1102  			NewOperationGe(SignedTypeInt32),
  1103  		)
  1104  	case wasm.OpcodeI32GeU:
  1105  		c.emit(
  1106  			NewOperationGe(SignedTypeUint32),
  1107  		)
  1108  	case wasm.OpcodeI64Eqz:
  1109  		c.emit(
  1110  			NewOperationEqz(UnsignedInt64),
  1111  		)
  1112  	case wasm.OpcodeI64Eq:
  1113  		c.emit(
  1114  			NewOperationEq(UnsignedTypeI64),
  1115  		)
  1116  	case wasm.OpcodeI64Ne:
  1117  		c.emit(
  1118  			NewOperationNe(UnsignedTypeI64),
  1119  		)
  1120  	case wasm.OpcodeI64LtS:
  1121  		c.emit(
  1122  			NewOperationLt(SignedTypeInt64),
  1123  		)
  1124  	case wasm.OpcodeI64LtU:
  1125  		c.emit(
  1126  			NewOperationLt(SignedTypeUint64),
  1127  		)
  1128  	case wasm.OpcodeI64GtS:
  1129  		c.emit(
  1130  			NewOperationGt(SignedTypeInt64),
  1131  		)
  1132  	case wasm.OpcodeI64GtU:
  1133  		c.emit(
  1134  			NewOperationGt(SignedTypeUint64),
  1135  		)
  1136  	case wasm.OpcodeI64LeS:
  1137  		c.emit(
  1138  			NewOperationLe(SignedTypeInt64),
  1139  		)
  1140  	case wasm.OpcodeI64LeU:
  1141  		c.emit(
  1142  			NewOperationLe(SignedTypeUint64),
  1143  		)
  1144  	case wasm.OpcodeI64GeS:
  1145  		c.emit(
  1146  			NewOperationGe(SignedTypeInt64),
  1147  		)
  1148  	case wasm.OpcodeI64GeU:
  1149  		c.emit(
  1150  			NewOperationGe(SignedTypeUint64),
  1151  		)
  1152  	case wasm.OpcodeF32Eq:
  1153  		c.emit(
  1154  			NewOperationEq(UnsignedTypeF32),
  1155  		)
  1156  	case wasm.OpcodeF32Ne:
  1157  		c.emit(
  1158  			NewOperationNe(UnsignedTypeF32),
  1159  		)
  1160  	case wasm.OpcodeF32Lt:
  1161  		c.emit(
  1162  			NewOperationLt(SignedTypeFloat32),
  1163  		)
  1164  	case wasm.OpcodeF32Gt:
  1165  		c.emit(
  1166  			NewOperationGt(SignedTypeFloat32),
  1167  		)
  1168  	case wasm.OpcodeF32Le:
  1169  		c.emit(
  1170  			NewOperationLe(SignedTypeFloat32),
  1171  		)
  1172  	case wasm.OpcodeF32Ge:
  1173  		c.emit(
  1174  			NewOperationGe(SignedTypeFloat32),
  1175  		)
  1176  	case wasm.OpcodeF64Eq:
  1177  		c.emit(
  1178  			NewOperationEq(UnsignedTypeF64),
  1179  		)
  1180  	case wasm.OpcodeF64Ne:
  1181  		c.emit(
  1182  			NewOperationNe(UnsignedTypeF64),
  1183  		)
  1184  	case wasm.OpcodeF64Lt:
  1185  		c.emit(
  1186  			NewOperationLt(SignedTypeFloat64),
  1187  		)
  1188  	case wasm.OpcodeF64Gt:
  1189  		c.emit(
  1190  			NewOperationGt(SignedTypeFloat64),
  1191  		)
  1192  	case wasm.OpcodeF64Le:
  1193  		c.emit(
  1194  			NewOperationLe(SignedTypeFloat64),
  1195  		)
  1196  	case wasm.OpcodeF64Ge:
  1197  		c.emit(
  1198  			NewOperationGe(SignedTypeFloat64),
  1199  		)
  1200  	case wasm.OpcodeI32Clz:
  1201  		c.emit(
  1202  			NewOperationClz(UnsignedInt32),
  1203  		)
  1204  	case wasm.OpcodeI32Ctz:
  1205  		c.emit(
  1206  			NewOperationCtz(UnsignedInt32),
  1207  		)
  1208  	case wasm.OpcodeI32Popcnt:
  1209  		c.emit(
  1210  			NewOperationPopcnt(UnsignedInt32),
  1211  		)
  1212  	case wasm.OpcodeI32Add:
  1213  		c.emit(
  1214  			NewOperationAdd(UnsignedTypeI32),
  1215  		)
  1216  	case wasm.OpcodeI32Sub:
  1217  		c.emit(
  1218  			NewOperationSub(UnsignedTypeI32),
  1219  		)
  1220  	case wasm.OpcodeI32Mul:
  1221  		c.emit(
  1222  			NewOperationMul(UnsignedTypeI32),
  1223  		)
  1224  	case wasm.OpcodeI32DivS:
  1225  		c.emit(
  1226  			NewOperationDiv(SignedTypeInt32),
  1227  		)
  1228  	case wasm.OpcodeI32DivU:
  1229  		c.emit(
  1230  			NewOperationDiv(SignedTypeUint32),
  1231  		)
  1232  	case wasm.OpcodeI32RemS:
  1233  		c.emit(
  1234  			NewOperationRem(SignedInt32),
  1235  		)
  1236  	case wasm.OpcodeI32RemU:
  1237  		c.emit(
  1238  			NewOperationRem(SignedUint32),
  1239  		)
  1240  	case wasm.OpcodeI32And:
  1241  		c.emit(
  1242  			NewOperationAnd(UnsignedInt32),
  1243  		)
  1244  	case wasm.OpcodeI32Or:
  1245  		c.emit(
  1246  			NewOperationOr(UnsignedInt32),
  1247  		)
  1248  	case wasm.OpcodeI32Xor:
  1249  		c.emit(
  1250  			NewOperationXor(UnsignedInt64),
  1251  		)
  1252  	case wasm.OpcodeI32Shl:
  1253  		c.emit(
  1254  			NewOperationShl(UnsignedInt32),
  1255  		)
  1256  	case wasm.OpcodeI32ShrS:
  1257  		c.emit(
  1258  			NewOperationShr(SignedInt32),
  1259  		)
  1260  	case wasm.OpcodeI32ShrU:
  1261  		c.emit(
  1262  			NewOperationShr(SignedUint32),
  1263  		)
  1264  	case wasm.OpcodeI32Rotl:
  1265  		c.emit(
  1266  			NewOperationRotl(UnsignedInt32),
  1267  		)
  1268  	case wasm.OpcodeI32Rotr:
  1269  		c.emit(
  1270  			NewOperationRotr(UnsignedInt32),
  1271  		)
  1272  	case wasm.OpcodeI64Clz:
  1273  		c.emit(
  1274  			NewOperationClz(UnsignedInt64),
  1275  		)
  1276  	case wasm.OpcodeI64Ctz:
  1277  		c.emit(
  1278  			NewOperationCtz(UnsignedInt64),
  1279  		)
  1280  	case wasm.OpcodeI64Popcnt:
  1281  		c.emit(
  1282  			NewOperationPopcnt(UnsignedInt64),
  1283  		)
  1284  	case wasm.OpcodeI64Add:
  1285  		c.emit(
  1286  			NewOperationAdd(UnsignedTypeI64),
  1287  		)
  1288  	case wasm.OpcodeI64Sub:
  1289  		c.emit(
  1290  			NewOperationSub(UnsignedTypeI64),
  1291  		)
  1292  	case wasm.OpcodeI64Mul:
  1293  		c.emit(
  1294  			NewOperationMul(UnsignedTypeI64),
  1295  		)
  1296  	case wasm.OpcodeI64DivS:
  1297  		c.emit(
  1298  			NewOperationDiv(SignedTypeInt64),
  1299  		)
  1300  	case wasm.OpcodeI64DivU:
  1301  		c.emit(
  1302  			NewOperationDiv(SignedTypeUint64),
  1303  		)
  1304  	case wasm.OpcodeI64RemS:
  1305  		c.emit(
  1306  			NewOperationRem(SignedInt64),
  1307  		)
  1308  	case wasm.OpcodeI64RemU:
  1309  		c.emit(
  1310  			NewOperationRem(SignedUint64),
  1311  		)
  1312  	case wasm.OpcodeI64And:
  1313  		c.emit(
  1314  			NewOperationAnd(UnsignedInt64),
  1315  		)
  1316  	case wasm.OpcodeI64Or:
  1317  		c.emit(
  1318  			NewOperationOr(UnsignedInt64),
  1319  		)
  1320  	case wasm.OpcodeI64Xor:
  1321  		c.emit(
  1322  			NewOperationXor(UnsignedInt64),
  1323  		)
  1324  	case wasm.OpcodeI64Shl:
  1325  		c.emit(
  1326  			NewOperationShl(UnsignedInt64),
  1327  		)
  1328  	case wasm.OpcodeI64ShrS:
  1329  		c.emit(
  1330  			NewOperationShr(SignedInt64),
  1331  		)
  1332  	case wasm.OpcodeI64ShrU:
  1333  		c.emit(
  1334  			NewOperationShr(SignedUint64),
  1335  		)
  1336  	case wasm.OpcodeI64Rotl:
  1337  		c.emit(
  1338  			NewOperationRotl(UnsignedInt64),
  1339  		)
  1340  	case wasm.OpcodeI64Rotr:
  1341  		c.emit(
  1342  			NewOperationRotr(UnsignedInt64),
  1343  		)
  1344  	case wasm.OpcodeF32Abs:
  1345  		c.emit(
  1346  			NewOperationAbs(Float32),
  1347  		)
  1348  	case wasm.OpcodeF32Neg:
  1349  		c.emit(
  1350  			NewOperationNeg(Float32),
  1351  		)
  1352  	case wasm.OpcodeF32Ceil:
  1353  		c.emit(
  1354  			NewOperationCeil(Float32),
  1355  		)
  1356  	case wasm.OpcodeF32Floor:
  1357  		c.emit(
  1358  			NewOperationFloor(Float32),
  1359  		)
  1360  	case wasm.OpcodeF32Trunc:
  1361  		c.emit(
  1362  			NewOperationTrunc(Float32),
  1363  		)
  1364  	case wasm.OpcodeF32Nearest:
  1365  		c.emit(
  1366  			NewOperationNearest(Float32),
  1367  		)
  1368  	case wasm.OpcodeF32Sqrt:
  1369  		c.emit(
  1370  			NewOperationSqrt(Float32),
  1371  		)
  1372  	case wasm.OpcodeF32Add:
  1373  		c.emit(
  1374  			NewOperationAdd(UnsignedTypeF32),
  1375  		)
  1376  	case wasm.OpcodeF32Sub:
  1377  		c.emit(
  1378  			NewOperationSub(UnsignedTypeF32),
  1379  		)
  1380  	case wasm.OpcodeF32Mul:
  1381  		c.emit(
  1382  			NewOperationMul(UnsignedTypeF32),
  1383  		)
  1384  	case wasm.OpcodeF32Div:
  1385  		c.emit(
  1386  			NewOperationDiv(SignedTypeFloat32),
  1387  		)
  1388  	case wasm.OpcodeF32Min:
  1389  		c.emit(
  1390  			NewOperationMin(Float32),
  1391  		)
  1392  	case wasm.OpcodeF32Max:
  1393  		c.emit(
  1394  			NewOperationMax(Float32),
  1395  		)
  1396  	case wasm.OpcodeF32Copysign:
  1397  		c.emit(
  1398  			NewOperationCopysign(Float32),
  1399  		)
  1400  	case wasm.OpcodeF64Abs:
  1401  		c.emit(
  1402  			NewOperationAbs(Float64),
  1403  		)
  1404  	case wasm.OpcodeF64Neg:
  1405  		c.emit(
  1406  			NewOperationNeg(Float64),
  1407  		)
  1408  	case wasm.OpcodeF64Ceil:
  1409  		c.emit(
  1410  			NewOperationCeil(Float64),
  1411  		)
  1412  	case wasm.OpcodeF64Floor:
  1413  		c.emit(
  1414  			NewOperationFloor(Float64),
  1415  		)
  1416  	case wasm.OpcodeF64Trunc:
  1417  		c.emit(
  1418  			NewOperationTrunc(Float64),
  1419  		)
  1420  	case wasm.OpcodeF64Nearest:
  1421  		c.emit(
  1422  			NewOperationNearest(Float64),
  1423  		)
  1424  	case wasm.OpcodeF64Sqrt:
  1425  		c.emit(
  1426  			NewOperationSqrt(Float64),
  1427  		)
  1428  	case wasm.OpcodeF64Add:
  1429  		c.emit(
  1430  			NewOperationAdd(UnsignedTypeF64),
  1431  		)
  1432  	case wasm.OpcodeF64Sub:
  1433  		c.emit(
  1434  			NewOperationSub(UnsignedTypeF64),
  1435  		)
  1436  	case wasm.OpcodeF64Mul:
  1437  		c.emit(
  1438  			NewOperationMul(UnsignedTypeF64),
  1439  		)
  1440  	case wasm.OpcodeF64Div:
  1441  		c.emit(
  1442  			NewOperationDiv(SignedTypeFloat64),
  1443  		)
  1444  	case wasm.OpcodeF64Min:
  1445  		c.emit(
  1446  			NewOperationMin(Float64),
  1447  		)
  1448  	case wasm.OpcodeF64Max:
  1449  		c.emit(
  1450  			NewOperationMax(Float64),
  1451  		)
  1452  	case wasm.OpcodeF64Copysign:
  1453  		c.emit(
  1454  			NewOperationCopysign(Float64),
  1455  		)
  1456  	case wasm.OpcodeI32WrapI64:
  1457  		c.emit(
  1458  			NewOperationI32WrapFromI64(),
  1459  		)
  1460  	case wasm.OpcodeI32TruncF32S:
  1461  		c.emit(
  1462  			NewOperationITruncFromF(Float32, SignedInt32, false),
  1463  		)
  1464  	case wasm.OpcodeI32TruncF32U:
  1465  		c.emit(
  1466  			NewOperationITruncFromF(Float32, SignedUint32, false),
  1467  		)
  1468  	case wasm.OpcodeI32TruncF64S:
  1469  		c.emit(
  1470  			NewOperationITruncFromF(Float64, SignedInt32, false),
  1471  		)
  1472  	case wasm.OpcodeI32TruncF64U:
  1473  		c.emit(
  1474  			NewOperationITruncFromF(Float64, SignedUint32, false),
  1475  		)
  1476  	case wasm.OpcodeI64ExtendI32S:
  1477  		c.emit(
  1478  			NewOperationExtend(true),
  1479  		)
  1480  	case wasm.OpcodeI64ExtendI32U:
  1481  		c.emit(
  1482  			NewOperationExtend(false),
  1483  		)
  1484  	case wasm.OpcodeI64TruncF32S:
  1485  		c.emit(
  1486  			NewOperationITruncFromF(Float32, SignedInt64, false),
  1487  		)
  1488  	case wasm.OpcodeI64TruncF32U:
  1489  		c.emit(
  1490  			NewOperationITruncFromF(Float32, SignedUint64, false),
  1491  		)
  1492  	case wasm.OpcodeI64TruncF64S:
  1493  		c.emit(
  1494  			NewOperationITruncFromF(Float64, SignedInt64, false),
  1495  		)
  1496  	case wasm.OpcodeI64TruncF64U:
  1497  		c.emit(
  1498  			NewOperationITruncFromF(Float64, SignedUint64, false),
  1499  		)
  1500  	case wasm.OpcodeF32ConvertI32S:
  1501  		c.emit(
  1502  			NewOperationFConvertFromI(SignedInt32, Float32),
  1503  		)
  1504  	case wasm.OpcodeF32ConvertI32U:
  1505  		c.emit(
  1506  			NewOperationFConvertFromI(SignedUint32, Float32),
  1507  		)
  1508  	case wasm.OpcodeF32ConvertI64S:
  1509  		c.emit(
  1510  			NewOperationFConvertFromI(SignedInt64, Float32),
  1511  		)
  1512  	case wasm.OpcodeF32ConvertI64U:
  1513  		c.emit(
  1514  			NewOperationFConvertFromI(SignedUint64, Float32),
  1515  		)
  1516  	case wasm.OpcodeF32DemoteF64:
  1517  		c.emit(
  1518  			NewOperationF32DemoteFromF64(),
  1519  		)
  1520  	case wasm.OpcodeF64ConvertI32S:
  1521  		c.emit(
  1522  			NewOperationFConvertFromI(SignedInt32, Float64),
  1523  		)
  1524  	case wasm.OpcodeF64ConvertI32U:
  1525  		c.emit(
  1526  			NewOperationFConvertFromI(SignedUint32, Float64),
  1527  		)
  1528  	case wasm.OpcodeF64ConvertI64S:
  1529  		c.emit(
  1530  			NewOperationFConvertFromI(SignedInt64, Float64),
  1531  		)
  1532  	case wasm.OpcodeF64ConvertI64U:
  1533  		c.emit(
  1534  			NewOperationFConvertFromI(SignedUint64, Float64),
  1535  		)
  1536  	case wasm.OpcodeF64PromoteF32:
  1537  		c.emit(
  1538  			NewOperationF64PromoteFromF32(),
  1539  		)
  1540  	case wasm.OpcodeI32ReinterpretF32:
  1541  		c.emit(
  1542  			NewOperationI32ReinterpretFromF32(),
  1543  		)
  1544  	case wasm.OpcodeI64ReinterpretF64:
  1545  		c.emit(
  1546  			NewOperationI64ReinterpretFromF64(),
  1547  		)
  1548  	case wasm.OpcodeF32ReinterpretI32:
  1549  		c.emit(
  1550  			NewOperationF32ReinterpretFromI32(),
  1551  		)
  1552  	case wasm.OpcodeF64ReinterpretI64:
  1553  		c.emit(
  1554  			NewOperationF64ReinterpretFromI64(),
  1555  		)
  1556  	case wasm.OpcodeI32Extend8S:
  1557  		c.emit(
  1558  			NewOperationSignExtend32From8(),
  1559  		)
  1560  	case wasm.OpcodeI32Extend16S:
  1561  		c.emit(
  1562  			NewOperationSignExtend32From16(),
  1563  		)
  1564  	case wasm.OpcodeI64Extend8S:
  1565  		c.emit(
  1566  			NewOperationSignExtend64From8(),
  1567  		)
  1568  	case wasm.OpcodeI64Extend16S:
  1569  		c.emit(
  1570  			NewOperationSignExtend64From16(),
  1571  		)
  1572  	case wasm.OpcodeI64Extend32S:
  1573  		c.emit(
  1574  			NewOperationSignExtend64From32(),
  1575  		)
  1576  	case wasm.OpcodeRefFunc:
  1577  		c.pc++
  1578  		index, num, err := leb128.LoadUint32(c.body[c.pc:])
  1579  		if err != nil {
  1580  			return fmt.Errorf("failed to read function index for ref.func: %v", err)
  1581  		}
  1582  		c.pc += num - 1
  1583  		c.emit(
  1584  			NewOperationRefFunc(index),
  1585  		)
  1586  	case wasm.OpcodeRefNull:
  1587  		c.pc++ // Skip the type of reftype as every ref value is opaque pointer.
  1588  		c.emit(
  1589  			NewOperationConstI64(0),
  1590  		)
  1591  	case wasm.OpcodeRefIsNull:
  1592  		// Simply compare the opaque pointer (i64) with zero.
  1593  		c.emit(
  1594  			NewOperationEqz(UnsignedInt64),
  1595  		)
  1596  	case wasm.OpcodeTableGet:
  1597  		c.pc++
  1598  		tableIndex, num, err := leb128.LoadUint32(c.body[c.pc:])
  1599  		if err != nil {
  1600  			return fmt.Errorf("failed to read function index for table.get: %v", err)
  1601  		}
  1602  		c.pc += num - 1
  1603  		c.emit(
  1604  			NewOperationTableGet(tableIndex),
  1605  		)
  1606  	case wasm.OpcodeTableSet:
  1607  		c.pc++
  1608  		tableIndex, num, err := leb128.LoadUint32(c.body[c.pc:])
  1609  		if err != nil {
  1610  			return fmt.Errorf("failed to read function index for table.set: %v", err)
  1611  		}
  1612  		c.pc += num - 1
  1613  		c.emit(
  1614  			NewOperationTableSet(tableIndex),
  1615  		)
  1616  	case wasm.OpcodeMiscPrefix:
  1617  		c.pc++
  1618  		// A misc opcode is encoded as an unsigned variable 32-bit integer.
  1619  		miscOp, num, err := leb128.LoadUint32(c.body[c.pc:])
  1620  		if err != nil {
  1621  			return fmt.Errorf("failed to read misc opcode: %v", err)
  1622  		}
  1623  		c.pc += num - 1
  1624  		switch byte(miscOp) {
  1625  		case wasm.OpcodeMiscI32TruncSatF32S:
  1626  			c.emit(
  1627  				NewOperationITruncFromF(Float32, SignedInt32, true),
  1628  			)
  1629  		case wasm.OpcodeMiscI32TruncSatF32U:
  1630  			c.emit(
  1631  				NewOperationITruncFromF(Float32, SignedUint32, true),
  1632  			)
  1633  		case wasm.OpcodeMiscI32TruncSatF64S:
  1634  			c.emit(
  1635  				NewOperationITruncFromF(Float64, SignedInt32, true),
  1636  			)
  1637  		case wasm.OpcodeMiscI32TruncSatF64U:
  1638  			c.emit(
  1639  				NewOperationITruncFromF(Float64, SignedUint32, true),
  1640  			)
  1641  		case wasm.OpcodeMiscI64TruncSatF32S:
  1642  			c.emit(
  1643  				NewOperationITruncFromF(Float32, SignedInt64, true),
  1644  			)
  1645  		case wasm.OpcodeMiscI64TruncSatF32U:
  1646  			c.emit(
  1647  				NewOperationITruncFromF(Float32, SignedUint64, true),
  1648  			)
  1649  		case wasm.OpcodeMiscI64TruncSatF64S:
  1650  			c.emit(
  1651  				NewOperationITruncFromF(Float64, SignedInt64, true),
  1652  			)
  1653  		case wasm.OpcodeMiscI64TruncSatF64U:
  1654  			c.emit(
  1655  				NewOperationITruncFromF(Float64, SignedUint64, true),
  1656  			)
  1657  		case wasm.OpcodeMiscMemoryInit:
  1658  			c.result.UsesMemory = true
  1659  			dataIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  1660  			if err != nil {
  1661  				return fmt.Errorf("reading i32.const value: %v", err)
  1662  			}
  1663  			c.pc += num + 1 // +1 to skip the memory index which is fixed to zero.
  1664  			c.emit(
  1665  				NewOperationMemoryInit(dataIndex),
  1666  			)
  1667  		case wasm.OpcodeMiscDataDrop:
  1668  			dataIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  1669  			if err != nil {
  1670  				return fmt.Errorf("reading i32.const value: %v", err)
  1671  			}
  1672  			c.pc += num
  1673  			c.emit(
  1674  				NewOperationDataDrop(dataIndex),
  1675  			)
  1676  		case wasm.OpcodeMiscMemoryCopy:
  1677  			c.result.UsesMemory = true
  1678  			c.pc += 2 // +2 to skip two memory indexes which are fixed to zero.
  1679  			c.emit(
  1680  				NewOperationMemoryCopy(),
  1681  			)
  1682  		case wasm.OpcodeMiscMemoryFill:
  1683  			c.result.UsesMemory = true
  1684  			c.pc += 1 // +1 to skip the memory index which is fixed to zero.
  1685  			c.emit(
  1686  				NewOperationMemoryFill(),
  1687  			)
  1688  		case wasm.OpcodeMiscTableInit:
  1689  			elemIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  1690  			if err != nil {
  1691  				return fmt.Errorf("reading i32.const value: %v", err)
  1692  			}
  1693  			c.pc += num
  1694  			// Read table index which is fixed to zero currently.
  1695  			tableIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  1696  			if err != nil {
  1697  				return fmt.Errorf("reading i32.const value: %v", err)
  1698  			}
  1699  			c.pc += num
  1700  			c.emit(
  1701  				NewOperationTableInit(elemIndex, tableIndex),
  1702  			)
  1703  		case wasm.OpcodeMiscElemDrop:
  1704  			elemIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  1705  			if err != nil {
  1706  				return fmt.Errorf("reading i32.const value: %v", err)
  1707  			}
  1708  			c.pc += num
  1709  			c.emit(
  1710  				NewOperationElemDrop(elemIndex),
  1711  			)
  1712  		case wasm.OpcodeMiscTableCopy:
  1713  			// Read the source table inde.g.
  1714  			dst, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  1715  			if err != nil {
  1716  				return fmt.Errorf("reading i32.const value: %v", err)
  1717  			}
  1718  			c.pc += num
  1719  			// Read the destination table inde.g.
  1720  			src, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  1721  			if err != nil {
  1722  				return fmt.Errorf("reading i32.const value: %v", err)
  1723  			}
  1724  			c.pc += num
  1725  			c.emit(
  1726  				NewOperationTableCopy(src, dst),
  1727  			)
  1728  		case wasm.OpcodeMiscTableGrow:
  1729  			// Read the source table inde.g.
  1730  			tableIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  1731  			if err != nil {
  1732  				return fmt.Errorf("reading i32.const value: %v", err)
  1733  			}
  1734  			c.pc += num
  1735  			c.emit(
  1736  				NewOperationTableGrow(tableIndex),
  1737  			)
  1738  		case wasm.OpcodeMiscTableSize:
  1739  			// Read the source table inde.g.
  1740  			tableIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  1741  			if err != nil {
  1742  				return fmt.Errorf("reading i32.const value: %v", err)
  1743  			}
  1744  			c.pc += num
  1745  			c.emit(
  1746  				NewOperationTableSize(tableIndex),
  1747  			)
  1748  		case wasm.OpcodeMiscTableFill:
  1749  			// Read the source table index.
  1750  			tableIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  1751  			if err != nil {
  1752  				return fmt.Errorf("reading i32.const value: %v", err)
  1753  			}
  1754  			c.pc += num
  1755  			c.emit(
  1756  				NewOperationTableFill(tableIndex),
  1757  			)
  1758  		default:
  1759  			return fmt.Errorf("unsupported misc instruction in wazeroir: 0x%x", op)
  1760  		}
  1761  	case wasm.OpcodeVecPrefix:
  1762  		c.pc++
  1763  		switch vecOp := c.body[c.pc]; vecOp {
  1764  		case wasm.OpcodeVecV128Const:
  1765  			c.pc++
  1766  			lo := binary.LittleEndian.Uint64(c.body[c.pc : c.pc+8])
  1767  			c.pc += 8
  1768  			hi := binary.LittleEndian.Uint64(c.body[c.pc : c.pc+8])
  1769  			c.emit(
  1770  				NewOperationV128Const(lo, hi),
  1771  			)
  1772  			c.pc += 7
  1773  		case wasm.OpcodeVecV128Load:
  1774  			arg, err := c.readMemoryArg(wasm.OpcodeI32LoadName)
  1775  			if err != nil {
  1776  				return err
  1777  			}
  1778  			c.emit(
  1779  				NewOperationV128Load(V128LoadType128, arg),
  1780  			)
  1781  		case wasm.OpcodeVecV128Load8x8s:
  1782  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load8x8SName)
  1783  			if err != nil {
  1784  				return err
  1785  			}
  1786  			c.emit(
  1787  				NewOperationV128Load(V128LoadType8x8s, arg),
  1788  			)
  1789  		case wasm.OpcodeVecV128Load8x8u:
  1790  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load8x8UName)
  1791  			if err != nil {
  1792  				return err
  1793  			}
  1794  			c.emit(
  1795  				NewOperationV128Load(V128LoadType8x8u, arg),
  1796  			)
  1797  		case wasm.OpcodeVecV128Load16x4s:
  1798  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load16x4SName)
  1799  			if err != nil {
  1800  				return err
  1801  			}
  1802  			c.emit(
  1803  				NewOperationV128Load(V128LoadType16x4s, arg),
  1804  			)
  1805  		case wasm.OpcodeVecV128Load16x4u:
  1806  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load16x4UName)
  1807  			if err != nil {
  1808  				return err
  1809  			}
  1810  			c.emit(
  1811  				NewOperationV128Load(V128LoadType16x4u, arg),
  1812  			)
  1813  		case wasm.OpcodeVecV128Load32x2s:
  1814  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32x2SName)
  1815  			if err != nil {
  1816  				return err
  1817  			}
  1818  			c.emit(
  1819  				NewOperationV128Load(V128LoadType32x2s, arg),
  1820  			)
  1821  		case wasm.OpcodeVecV128Load32x2u:
  1822  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32x2UName)
  1823  			if err != nil {
  1824  				return err
  1825  			}
  1826  			c.emit(
  1827  				NewOperationV128Load(V128LoadType32x2u, arg),
  1828  			)
  1829  		case wasm.OpcodeVecV128Load8Splat:
  1830  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load8SplatName)
  1831  			if err != nil {
  1832  				return err
  1833  			}
  1834  			c.emit(
  1835  				NewOperationV128Load(V128LoadType8Splat, arg),
  1836  			)
  1837  		case wasm.OpcodeVecV128Load16Splat:
  1838  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load16SplatName)
  1839  			if err != nil {
  1840  				return err
  1841  			}
  1842  			c.emit(
  1843  				NewOperationV128Load(V128LoadType16Splat, arg),
  1844  			)
  1845  		case wasm.OpcodeVecV128Load32Splat:
  1846  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32SplatName)
  1847  			if err != nil {
  1848  				return err
  1849  			}
  1850  			c.emit(
  1851  				NewOperationV128Load(V128LoadType32Splat, arg),
  1852  			)
  1853  		case wasm.OpcodeVecV128Load64Splat:
  1854  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load64SplatName)
  1855  			if err != nil {
  1856  				return err
  1857  			}
  1858  			c.emit(
  1859  				NewOperationV128Load(V128LoadType64Splat, arg),
  1860  			)
  1861  		case wasm.OpcodeVecV128Load32zero:
  1862  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32zeroName)
  1863  			if err != nil {
  1864  				return err
  1865  			}
  1866  			c.emit(
  1867  				NewOperationV128Load(V128LoadType32zero, arg),
  1868  			)
  1869  		case wasm.OpcodeVecV128Load64zero:
  1870  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load64zeroName)
  1871  			if err != nil {
  1872  				return err
  1873  			}
  1874  			c.emit(
  1875  				NewOperationV128Load(V128LoadType64zero, arg),
  1876  			)
  1877  		case wasm.OpcodeVecV128Load8Lane:
  1878  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load8LaneName)
  1879  			if err != nil {
  1880  				return err
  1881  			}
  1882  			c.pc++
  1883  			laneIndex := c.body[c.pc]
  1884  			c.emit(
  1885  				NewOperationV128LoadLane(laneIndex, 8, arg),
  1886  			)
  1887  		case wasm.OpcodeVecV128Load16Lane:
  1888  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load16LaneName)
  1889  			if err != nil {
  1890  				return err
  1891  			}
  1892  			c.pc++
  1893  			laneIndex := c.body[c.pc]
  1894  			c.emit(
  1895  				NewOperationV128LoadLane(laneIndex, 16, arg),
  1896  			)
  1897  		case wasm.OpcodeVecV128Load32Lane:
  1898  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32LaneName)
  1899  			if err != nil {
  1900  				return err
  1901  			}
  1902  			c.pc++
  1903  			laneIndex := c.body[c.pc]
  1904  			c.emit(
  1905  				NewOperationV128LoadLane(laneIndex, 32, arg),
  1906  			)
  1907  		case wasm.OpcodeVecV128Load64Lane:
  1908  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load64LaneName)
  1909  			if err != nil {
  1910  				return err
  1911  			}
  1912  			c.pc++
  1913  			laneIndex := c.body[c.pc]
  1914  			c.emit(
  1915  				NewOperationV128LoadLane(laneIndex, 64, arg),
  1916  			)
  1917  		case wasm.OpcodeVecV128Store:
  1918  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128StoreName)
  1919  			if err != nil {
  1920  				return err
  1921  			}
  1922  			c.emit(
  1923  				NewOperationV128Store(arg),
  1924  			)
  1925  		case wasm.OpcodeVecV128Store8Lane:
  1926  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Store8LaneName)
  1927  			if err != nil {
  1928  				return err
  1929  			}
  1930  			c.pc++
  1931  			laneIndex := c.body[c.pc]
  1932  			c.emit(
  1933  				NewOperationV128StoreLane(laneIndex, 8, arg),
  1934  			)
  1935  		case wasm.OpcodeVecV128Store16Lane:
  1936  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Store16LaneName)
  1937  			if err != nil {
  1938  				return err
  1939  			}
  1940  			c.pc++
  1941  			laneIndex := c.body[c.pc]
  1942  			c.emit(
  1943  				NewOperationV128StoreLane(laneIndex, 16, arg),
  1944  			)
  1945  		case wasm.OpcodeVecV128Store32Lane:
  1946  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Store32LaneName)
  1947  			if err != nil {
  1948  				return err
  1949  			}
  1950  			c.pc++
  1951  			laneIndex := c.body[c.pc]
  1952  			c.emit(
  1953  				NewOperationV128StoreLane(laneIndex, 32, arg),
  1954  			)
  1955  		case wasm.OpcodeVecV128Store64Lane:
  1956  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Store64LaneName)
  1957  			if err != nil {
  1958  				return err
  1959  			}
  1960  			c.pc++
  1961  			laneIndex := c.body[c.pc]
  1962  			c.emit(
  1963  				NewOperationV128StoreLane(laneIndex, 64, arg),
  1964  			)
  1965  		case wasm.OpcodeVecI8x16ExtractLaneS:
  1966  			c.pc++
  1967  			laneIndex := c.body[c.pc]
  1968  			c.emit(
  1969  				NewOperationV128ExtractLane(laneIndex, true, ShapeI8x16),
  1970  			)
  1971  		case wasm.OpcodeVecI8x16ExtractLaneU:
  1972  			c.pc++
  1973  			laneIndex := c.body[c.pc]
  1974  			c.emit(
  1975  				NewOperationV128ExtractLane(laneIndex, false, ShapeI8x16),
  1976  			)
  1977  		case wasm.OpcodeVecI16x8ExtractLaneS:
  1978  			c.pc++
  1979  			laneIndex := c.body[c.pc]
  1980  			c.emit(
  1981  				NewOperationV128ExtractLane(laneIndex, true, ShapeI16x8),
  1982  			)
  1983  		case wasm.OpcodeVecI16x8ExtractLaneU:
  1984  			c.pc++
  1985  			laneIndex := c.body[c.pc]
  1986  			c.emit(
  1987  				NewOperationV128ExtractLane(laneIndex, false, ShapeI16x8),
  1988  			)
  1989  		case wasm.OpcodeVecI32x4ExtractLane:
  1990  			c.pc++
  1991  			laneIndex := c.body[c.pc]
  1992  			c.emit(
  1993  				NewOperationV128ExtractLane(laneIndex, false, ShapeI32x4),
  1994  			)
  1995  		case wasm.OpcodeVecI64x2ExtractLane:
  1996  			c.pc++
  1997  			laneIndex := c.body[c.pc]
  1998  			c.emit(
  1999  				NewOperationV128ExtractLane(laneIndex, false, ShapeI64x2),
  2000  			)
  2001  		case wasm.OpcodeVecF32x4ExtractLane:
  2002  			c.pc++
  2003  			laneIndex := c.body[c.pc]
  2004  			c.emit(
  2005  				NewOperationV128ExtractLane(laneIndex, false, ShapeF32x4),
  2006  			)
  2007  		case wasm.OpcodeVecF64x2ExtractLane:
  2008  			c.pc++
  2009  			laneIndex := c.body[c.pc]
  2010  			c.emit(
  2011  				NewOperationV128ExtractLane(laneIndex, false, ShapeF64x2),
  2012  			)
  2013  		case wasm.OpcodeVecI8x16ReplaceLane:
  2014  			c.pc++
  2015  			laneIndex := c.body[c.pc]
  2016  			c.emit(
  2017  				NewOperationV128ReplaceLane(laneIndex, ShapeI8x16),
  2018  			)
  2019  		case wasm.OpcodeVecI16x8ReplaceLane:
  2020  			c.pc++
  2021  			laneIndex := c.body[c.pc]
  2022  			c.emit(
  2023  				NewOperationV128ReplaceLane(laneIndex, ShapeI16x8),
  2024  			)
  2025  		case wasm.OpcodeVecI32x4ReplaceLane:
  2026  			c.pc++
  2027  			laneIndex := c.body[c.pc]
  2028  			c.emit(
  2029  				NewOperationV128ReplaceLane(laneIndex, ShapeI32x4),
  2030  			)
  2031  		case wasm.OpcodeVecI64x2ReplaceLane:
  2032  			c.pc++
  2033  			laneIndex := c.body[c.pc]
  2034  			c.emit(
  2035  				NewOperationV128ReplaceLane(laneIndex, ShapeI64x2),
  2036  			)
  2037  		case wasm.OpcodeVecF32x4ReplaceLane:
  2038  			c.pc++
  2039  			laneIndex := c.body[c.pc]
  2040  			c.emit(
  2041  				NewOperationV128ReplaceLane(laneIndex, ShapeF32x4),
  2042  			)
  2043  		case wasm.OpcodeVecF64x2ReplaceLane:
  2044  			c.pc++
  2045  			laneIndex := c.body[c.pc]
  2046  			c.emit(
  2047  				NewOperationV128ReplaceLane(laneIndex, ShapeF64x2),
  2048  			)
  2049  		case wasm.OpcodeVecI8x16Splat:
  2050  			c.emit(
  2051  				NewOperationV128Splat(ShapeI8x16),
  2052  			)
  2053  		case wasm.OpcodeVecI16x8Splat:
  2054  			c.emit(
  2055  				NewOperationV128Splat(ShapeI16x8),
  2056  			)
  2057  		case wasm.OpcodeVecI32x4Splat:
  2058  			c.emit(
  2059  				NewOperationV128Splat(ShapeI32x4),
  2060  			)
  2061  		case wasm.OpcodeVecI64x2Splat:
  2062  			c.emit(
  2063  				NewOperationV128Splat(ShapeI64x2),
  2064  			)
  2065  		case wasm.OpcodeVecF32x4Splat:
  2066  			c.emit(
  2067  				NewOperationV128Splat(ShapeF32x4),
  2068  			)
  2069  		case wasm.OpcodeVecF64x2Splat:
  2070  			c.emit(
  2071  				NewOperationV128Splat(ShapeF64x2),
  2072  			)
  2073  		case wasm.OpcodeVecI8x16Swizzle:
  2074  			c.emit(
  2075  				NewOperationV128Swizzle(),
  2076  			)
  2077  		case wasm.OpcodeVecV128i8x16Shuffle:
  2078  			c.pc++
  2079  			lanes := make([]uint64, 16)
  2080  			for i := uint64(0); i < 16; i++ {
  2081  				lanes[i] = uint64(c.body[c.pc+i])
  2082  			}
  2083  			op := NewOperationV128Shuffle(lanes)
  2084  			c.emit(op)
  2085  			c.pc += 15
  2086  		case wasm.OpcodeVecV128AnyTrue:
  2087  			c.emit(
  2088  				NewOperationV128AnyTrue(),
  2089  			)
  2090  		case wasm.OpcodeVecI8x16AllTrue:
  2091  			c.emit(
  2092  				NewOperationV128AllTrue(ShapeI8x16),
  2093  			)
  2094  		case wasm.OpcodeVecI16x8AllTrue:
  2095  			c.emit(
  2096  				NewOperationV128AllTrue(ShapeI16x8),
  2097  			)
  2098  		case wasm.OpcodeVecI32x4AllTrue:
  2099  			c.emit(
  2100  				NewOperationV128AllTrue(ShapeI32x4),
  2101  			)
  2102  		case wasm.OpcodeVecI64x2AllTrue:
  2103  			c.emit(
  2104  				NewOperationV128AllTrue(ShapeI64x2),
  2105  			)
  2106  		case wasm.OpcodeVecI8x16BitMask:
  2107  			c.emit(
  2108  				NewOperationV128BitMask(ShapeI8x16),
  2109  			)
  2110  		case wasm.OpcodeVecI16x8BitMask:
  2111  			c.emit(
  2112  				NewOperationV128BitMask(ShapeI16x8),
  2113  			)
  2114  		case wasm.OpcodeVecI32x4BitMask:
  2115  			c.emit(
  2116  				NewOperationV128BitMask(ShapeI32x4),
  2117  			)
  2118  		case wasm.OpcodeVecI64x2BitMask:
  2119  			c.emit(
  2120  				NewOperationV128BitMask(ShapeI64x2),
  2121  			)
  2122  		case wasm.OpcodeVecV128And:
  2123  			c.emit(
  2124  				NewOperationV128And(),
  2125  			)
  2126  		case wasm.OpcodeVecV128Not:
  2127  			c.emit(
  2128  				NewOperationV128Not(),
  2129  			)
  2130  		case wasm.OpcodeVecV128Or:
  2131  			c.emit(
  2132  				NewOperationV128Or(),
  2133  			)
  2134  		case wasm.OpcodeVecV128Xor:
  2135  			c.emit(
  2136  				NewOperationV128Xor(),
  2137  			)
  2138  		case wasm.OpcodeVecV128Bitselect:
  2139  			c.emit(
  2140  				NewOperationV128Bitselect(),
  2141  			)
  2142  		case wasm.OpcodeVecV128AndNot:
  2143  			c.emit(
  2144  				NewOperationV128AndNot(),
  2145  			)
  2146  		case wasm.OpcodeVecI8x16Shl:
  2147  			c.emit(
  2148  				NewOperationV128Shl(ShapeI8x16),
  2149  			)
  2150  		case wasm.OpcodeVecI8x16ShrS:
  2151  			c.emit(
  2152  				NewOperationV128Shr(ShapeI8x16, true),
  2153  			)
  2154  		case wasm.OpcodeVecI8x16ShrU:
  2155  			c.emit(
  2156  				NewOperationV128Shr(ShapeI8x16, false),
  2157  			)
  2158  		case wasm.OpcodeVecI16x8Shl:
  2159  			c.emit(
  2160  				NewOperationV128Shl(ShapeI16x8),
  2161  			)
  2162  		case wasm.OpcodeVecI16x8ShrS:
  2163  			c.emit(
  2164  				NewOperationV128Shr(ShapeI16x8, true),
  2165  			)
  2166  		case wasm.OpcodeVecI16x8ShrU:
  2167  			c.emit(
  2168  				NewOperationV128Shr(ShapeI16x8, false),
  2169  			)
  2170  		case wasm.OpcodeVecI32x4Shl:
  2171  			c.emit(
  2172  				NewOperationV128Shl(ShapeI32x4),
  2173  			)
  2174  		case wasm.OpcodeVecI32x4ShrS:
  2175  			c.emit(
  2176  				NewOperationV128Shr(ShapeI32x4, true),
  2177  			)
  2178  		case wasm.OpcodeVecI32x4ShrU:
  2179  			c.emit(
  2180  				NewOperationV128Shr(ShapeI32x4, false),
  2181  			)
  2182  		case wasm.OpcodeVecI64x2Shl:
  2183  			c.emit(
  2184  				NewOperationV128Shl(ShapeI64x2),
  2185  			)
  2186  		case wasm.OpcodeVecI64x2ShrS:
  2187  			c.emit(
  2188  				NewOperationV128Shr(ShapeI64x2, true),
  2189  			)
  2190  		case wasm.OpcodeVecI64x2ShrU:
  2191  			c.emit(
  2192  				NewOperationV128Shr(ShapeI64x2, false),
  2193  			)
  2194  		case wasm.OpcodeVecI8x16Eq:
  2195  			c.emit(
  2196  				NewOperationV128Cmp(V128CmpTypeI8x16Eq),
  2197  			)
  2198  		case wasm.OpcodeVecI8x16Ne:
  2199  			c.emit(
  2200  				NewOperationV128Cmp(V128CmpTypeI8x16Ne),
  2201  			)
  2202  		case wasm.OpcodeVecI8x16LtS:
  2203  			c.emit(
  2204  				NewOperationV128Cmp(V128CmpTypeI8x16LtS),
  2205  			)
  2206  		case wasm.OpcodeVecI8x16LtU:
  2207  			c.emit(
  2208  				NewOperationV128Cmp(V128CmpTypeI8x16LtU),
  2209  			)
  2210  		case wasm.OpcodeVecI8x16GtS:
  2211  			c.emit(
  2212  				NewOperationV128Cmp(V128CmpTypeI8x16GtS),
  2213  			)
  2214  		case wasm.OpcodeVecI8x16GtU:
  2215  			c.emit(
  2216  				NewOperationV128Cmp(V128CmpTypeI8x16GtU),
  2217  			)
  2218  		case wasm.OpcodeVecI8x16LeS:
  2219  			c.emit(
  2220  				NewOperationV128Cmp(V128CmpTypeI8x16LeS),
  2221  			)
  2222  		case wasm.OpcodeVecI8x16LeU:
  2223  			c.emit(
  2224  				NewOperationV128Cmp(V128CmpTypeI8x16LeU),
  2225  			)
  2226  		case wasm.OpcodeVecI8x16GeS:
  2227  			c.emit(
  2228  				NewOperationV128Cmp(V128CmpTypeI8x16GeS),
  2229  			)
  2230  		case wasm.OpcodeVecI8x16GeU:
  2231  			c.emit(
  2232  				NewOperationV128Cmp(V128CmpTypeI8x16GeU),
  2233  			)
  2234  		case wasm.OpcodeVecI16x8Eq:
  2235  			c.emit(
  2236  				NewOperationV128Cmp(V128CmpTypeI16x8Eq),
  2237  			)
  2238  		case wasm.OpcodeVecI16x8Ne:
  2239  			c.emit(
  2240  				NewOperationV128Cmp(V128CmpTypeI16x8Ne),
  2241  			)
  2242  		case wasm.OpcodeVecI16x8LtS:
  2243  			c.emit(
  2244  				NewOperationV128Cmp(V128CmpTypeI16x8LtS),
  2245  			)
  2246  		case wasm.OpcodeVecI16x8LtU:
  2247  			c.emit(
  2248  				NewOperationV128Cmp(V128CmpTypeI16x8LtU),
  2249  			)
  2250  		case wasm.OpcodeVecI16x8GtS:
  2251  			c.emit(
  2252  				NewOperationV128Cmp(V128CmpTypeI16x8GtS),
  2253  			)
  2254  		case wasm.OpcodeVecI16x8GtU:
  2255  			c.emit(
  2256  				NewOperationV128Cmp(V128CmpTypeI16x8GtU),
  2257  			)
  2258  		case wasm.OpcodeVecI16x8LeS:
  2259  			c.emit(
  2260  				NewOperationV128Cmp(V128CmpTypeI16x8LeS),
  2261  			)
  2262  		case wasm.OpcodeVecI16x8LeU:
  2263  			c.emit(
  2264  				NewOperationV128Cmp(V128CmpTypeI16x8LeU),
  2265  			)
  2266  		case wasm.OpcodeVecI16x8GeS:
  2267  			c.emit(
  2268  				NewOperationV128Cmp(V128CmpTypeI16x8GeS),
  2269  			)
  2270  		case wasm.OpcodeVecI16x8GeU:
  2271  			c.emit(
  2272  				NewOperationV128Cmp(V128CmpTypeI16x8GeU),
  2273  			)
  2274  		case wasm.OpcodeVecI32x4Eq:
  2275  			c.emit(
  2276  				NewOperationV128Cmp(V128CmpTypeI32x4Eq),
  2277  			)
  2278  		case wasm.OpcodeVecI32x4Ne:
  2279  			c.emit(
  2280  				NewOperationV128Cmp(V128CmpTypeI32x4Ne),
  2281  			)
  2282  		case wasm.OpcodeVecI32x4LtS:
  2283  			c.emit(
  2284  				NewOperationV128Cmp(V128CmpTypeI32x4LtS),
  2285  			)
  2286  		case wasm.OpcodeVecI32x4LtU:
  2287  			c.emit(
  2288  				NewOperationV128Cmp(V128CmpTypeI32x4LtU),
  2289  			)
  2290  		case wasm.OpcodeVecI32x4GtS:
  2291  			c.emit(
  2292  				NewOperationV128Cmp(V128CmpTypeI32x4GtS),
  2293  			)
  2294  		case wasm.OpcodeVecI32x4GtU:
  2295  			c.emit(
  2296  				NewOperationV128Cmp(V128CmpTypeI32x4GtU),
  2297  			)
  2298  		case wasm.OpcodeVecI32x4LeS:
  2299  			c.emit(
  2300  				NewOperationV128Cmp(V128CmpTypeI32x4LeS),
  2301  			)
  2302  		case wasm.OpcodeVecI32x4LeU:
  2303  			c.emit(
  2304  				NewOperationV128Cmp(V128CmpTypeI32x4LeU),
  2305  			)
  2306  		case wasm.OpcodeVecI32x4GeS:
  2307  			c.emit(
  2308  				NewOperationV128Cmp(V128CmpTypeI32x4GeS),
  2309  			)
  2310  		case wasm.OpcodeVecI32x4GeU:
  2311  			c.emit(
  2312  				NewOperationV128Cmp(V128CmpTypeI32x4GeU),
  2313  			)
  2314  		case wasm.OpcodeVecI64x2Eq:
  2315  			c.emit(
  2316  				NewOperationV128Cmp(V128CmpTypeI64x2Eq),
  2317  			)
  2318  		case wasm.OpcodeVecI64x2Ne:
  2319  			c.emit(
  2320  				NewOperationV128Cmp(V128CmpTypeI64x2Ne),
  2321  			)
  2322  		case wasm.OpcodeVecI64x2LtS:
  2323  			c.emit(
  2324  				NewOperationV128Cmp(V128CmpTypeI64x2LtS),
  2325  			)
  2326  		case wasm.OpcodeVecI64x2GtS:
  2327  			c.emit(
  2328  				NewOperationV128Cmp(V128CmpTypeI64x2GtS),
  2329  			)
  2330  		case wasm.OpcodeVecI64x2LeS:
  2331  			c.emit(
  2332  				NewOperationV128Cmp(V128CmpTypeI64x2LeS),
  2333  			)
  2334  		case wasm.OpcodeVecI64x2GeS:
  2335  			c.emit(
  2336  				NewOperationV128Cmp(V128CmpTypeI64x2GeS),
  2337  			)
  2338  		case wasm.OpcodeVecF32x4Eq:
  2339  			c.emit(
  2340  				NewOperationV128Cmp(V128CmpTypeF32x4Eq),
  2341  			)
  2342  		case wasm.OpcodeVecF32x4Ne:
  2343  			c.emit(
  2344  				NewOperationV128Cmp(V128CmpTypeF32x4Ne),
  2345  			)
  2346  		case wasm.OpcodeVecF32x4Lt:
  2347  			c.emit(
  2348  				NewOperationV128Cmp(V128CmpTypeF32x4Lt),
  2349  			)
  2350  		case wasm.OpcodeVecF32x4Gt:
  2351  			c.emit(
  2352  				NewOperationV128Cmp(V128CmpTypeF32x4Gt),
  2353  			)
  2354  		case wasm.OpcodeVecF32x4Le:
  2355  			c.emit(
  2356  				NewOperationV128Cmp(V128CmpTypeF32x4Le),
  2357  			)
  2358  		case wasm.OpcodeVecF32x4Ge:
  2359  			c.emit(
  2360  				NewOperationV128Cmp(V128CmpTypeF32x4Ge),
  2361  			)
  2362  		case wasm.OpcodeVecF64x2Eq:
  2363  			c.emit(
  2364  				NewOperationV128Cmp(V128CmpTypeF64x2Eq),
  2365  			)
  2366  		case wasm.OpcodeVecF64x2Ne:
  2367  			c.emit(
  2368  				NewOperationV128Cmp(V128CmpTypeF64x2Ne),
  2369  			)
  2370  		case wasm.OpcodeVecF64x2Lt:
  2371  			c.emit(
  2372  				NewOperationV128Cmp(V128CmpTypeF64x2Lt),
  2373  			)
  2374  		case wasm.OpcodeVecF64x2Gt:
  2375  			c.emit(
  2376  				NewOperationV128Cmp(V128CmpTypeF64x2Gt),
  2377  			)
  2378  		case wasm.OpcodeVecF64x2Le:
  2379  			c.emit(
  2380  				NewOperationV128Cmp(V128CmpTypeF64x2Le),
  2381  			)
  2382  		case wasm.OpcodeVecF64x2Ge:
  2383  			c.emit(
  2384  				NewOperationV128Cmp(V128CmpTypeF64x2Ge),
  2385  			)
  2386  		case wasm.OpcodeVecI8x16Neg:
  2387  			c.emit(
  2388  				NewOperationV128Neg(ShapeI8x16),
  2389  			)
  2390  		case wasm.OpcodeVecI16x8Neg:
  2391  			c.emit(
  2392  				NewOperationV128Neg(ShapeI16x8),
  2393  			)
  2394  		case wasm.OpcodeVecI32x4Neg:
  2395  			c.emit(
  2396  				NewOperationV128Neg(ShapeI32x4),
  2397  			)
  2398  		case wasm.OpcodeVecI64x2Neg:
  2399  			c.emit(
  2400  				NewOperationV128Neg(ShapeI64x2),
  2401  			)
  2402  		case wasm.OpcodeVecF32x4Neg:
  2403  			c.emit(
  2404  				NewOperationV128Neg(ShapeF32x4),
  2405  			)
  2406  		case wasm.OpcodeVecF64x2Neg:
  2407  			c.emit(
  2408  				NewOperationV128Neg(ShapeF64x2),
  2409  			)
  2410  		case wasm.OpcodeVecI8x16Add:
  2411  			c.emit(
  2412  				NewOperationV128Add(ShapeI8x16),
  2413  			)
  2414  		case wasm.OpcodeVecI16x8Add:
  2415  			c.emit(
  2416  				NewOperationV128Add(ShapeI16x8),
  2417  			)
  2418  		case wasm.OpcodeVecI32x4Add:
  2419  			c.emit(
  2420  				NewOperationV128Add(ShapeI32x4),
  2421  			)
  2422  		case wasm.OpcodeVecI64x2Add:
  2423  			c.emit(
  2424  				NewOperationV128Add(ShapeI64x2),
  2425  			)
  2426  		case wasm.OpcodeVecF32x4Add:
  2427  			c.emit(
  2428  				NewOperationV128Add(ShapeF32x4),
  2429  			)
  2430  		case wasm.OpcodeVecF64x2Add:
  2431  			c.emit(
  2432  				NewOperationV128Add(ShapeF64x2),
  2433  			)
  2434  		case wasm.OpcodeVecI8x16Sub:
  2435  			c.emit(
  2436  				NewOperationV128Sub(ShapeI8x16),
  2437  			)
  2438  		case wasm.OpcodeVecI16x8Sub:
  2439  			c.emit(
  2440  				NewOperationV128Sub(ShapeI16x8),
  2441  			)
  2442  		case wasm.OpcodeVecI32x4Sub:
  2443  			c.emit(
  2444  				NewOperationV128Sub(ShapeI32x4),
  2445  			)
  2446  		case wasm.OpcodeVecI64x2Sub:
  2447  			c.emit(
  2448  				NewOperationV128Sub(ShapeI64x2),
  2449  			)
  2450  		case wasm.OpcodeVecF32x4Sub:
  2451  			c.emit(
  2452  				NewOperationV128Sub(ShapeF32x4),
  2453  			)
  2454  		case wasm.OpcodeVecF64x2Sub:
  2455  			c.emit(
  2456  				NewOperationV128Sub(ShapeF64x2),
  2457  			)
  2458  		case wasm.OpcodeVecI8x16AddSatS:
  2459  			c.emit(
  2460  				NewOperationV128AddSat(ShapeI8x16, true),
  2461  			)
  2462  		case wasm.OpcodeVecI8x16AddSatU:
  2463  			c.emit(
  2464  				NewOperationV128AddSat(ShapeI8x16, false),
  2465  			)
  2466  		case wasm.OpcodeVecI16x8AddSatS:
  2467  			c.emit(
  2468  				NewOperationV128AddSat(ShapeI16x8, true),
  2469  			)
  2470  		case wasm.OpcodeVecI16x8AddSatU:
  2471  			c.emit(
  2472  				NewOperationV128AddSat(ShapeI16x8, false),
  2473  			)
  2474  		case wasm.OpcodeVecI8x16SubSatS:
  2475  			c.emit(
  2476  				NewOperationV128SubSat(ShapeI8x16, true),
  2477  			)
  2478  		case wasm.OpcodeVecI8x16SubSatU:
  2479  			c.emit(
  2480  				NewOperationV128SubSat(ShapeI8x16, false),
  2481  			)
  2482  		case wasm.OpcodeVecI16x8SubSatS:
  2483  			c.emit(
  2484  				NewOperationV128SubSat(ShapeI16x8, true),
  2485  			)
  2486  		case wasm.OpcodeVecI16x8SubSatU:
  2487  			c.emit(
  2488  				NewOperationV128SubSat(ShapeI16x8, false),
  2489  			)
  2490  		case wasm.OpcodeVecI16x8Mul:
  2491  			c.emit(
  2492  				NewOperationV128Mul(ShapeI16x8),
  2493  			)
  2494  		case wasm.OpcodeVecI32x4Mul:
  2495  			c.emit(
  2496  				NewOperationV128Mul(ShapeI32x4),
  2497  			)
  2498  		case wasm.OpcodeVecI64x2Mul:
  2499  			c.emit(
  2500  				NewOperationV128Mul(ShapeI64x2),
  2501  			)
  2502  		case wasm.OpcodeVecF32x4Mul:
  2503  			c.emit(
  2504  				NewOperationV128Mul(ShapeF32x4),
  2505  			)
  2506  		case wasm.OpcodeVecF64x2Mul:
  2507  			c.emit(
  2508  				NewOperationV128Mul(ShapeF64x2),
  2509  			)
  2510  		case wasm.OpcodeVecF32x4Sqrt:
  2511  			c.emit(
  2512  				NewOperationV128Sqrt(ShapeF32x4),
  2513  			)
  2514  		case wasm.OpcodeVecF64x2Sqrt:
  2515  			c.emit(
  2516  				NewOperationV128Sqrt(ShapeF64x2),
  2517  			)
  2518  		case wasm.OpcodeVecF32x4Div:
  2519  			c.emit(
  2520  				NewOperationV128Div(ShapeF32x4),
  2521  			)
  2522  		case wasm.OpcodeVecF64x2Div:
  2523  			c.emit(
  2524  				NewOperationV128Div(ShapeF64x2),
  2525  			)
  2526  		case wasm.OpcodeVecI8x16Abs:
  2527  			c.emit(
  2528  				NewOperationV128Abs(ShapeI8x16),
  2529  			)
  2530  		case wasm.OpcodeVecI8x16Popcnt:
  2531  			c.emit(
  2532  				NewOperationV128Popcnt(ShapeI8x16),
  2533  			)
  2534  		case wasm.OpcodeVecI16x8Abs:
  2535  			c.emit(
  2536  				NewOperationV128Abs(ShapeI16x8),
  2537  			)
  2538  		case wasm.OpcodeVecI32x4Abs:
  2539  			c.emit(
  2540  				NewOperationV128Abs(ShapeI32x4),
  2541  			)
  2542  		case wasm.OpcodeVecI64x2Abs:
  2543  			c.emit(
  2544  				NewOperationV128Abs(ShapeI64x2),
  2545  			)
  2546  		case wasm.OpcodeVecF32x4Abs:
  2547  			c.emit(
  2548  				NewOperationV128Abs(ShapeF32x4),
  2549  			)
  2550  		case wasm.OpcodeVecF64x2Abs:
  2551  			c.emit(
  2552  				NewOperationV128Abs(ShapeF64x2),
  2553  			)
  2554  		case wasm.OpcodeVecI8x16MinS:
  2555  			c.emit(
  2556  				NewOperationV128Min(ShapeI8x16, true),
  2557  			)
  2558  		case wasm.OpcodeVecI8x16MinU:
  2559  			c.emit(
  2560  				NewOperationV128Min(ShapeI8x16, false),
  2561  			)
  2562  		case wasm.OpcodeVecI8x16MaxS:
  2563  			c.emit(
  2564  				NewOperationV128Max(ShapeI8x16, true),
  2565  			)
  2566  		case wasm.OpcodeVecI8x16MaxU:
  2567  			c.emit(
  2568  				NewOperationV128Max(ShapeI8x16, false),
  2569  			)
  2570  		case wasm.OpcodeVecI8x16AvgrU:
  2571  			c.emit(
  2572  				NewOperationV128AvgrU(ShapeI8x16),
  2573  			)
  2574  		case wasm.OpcodeVecI16x8MinS:
  2575  			c.emit(
  2576  				NewOperationV128Min(ShapeI16x8, true),
  2577  			)
  2578  		case wasm.OpcodeVecI16x8MinU:
  2579  			c.emit(
  2580  				NewOperationV128Min(ShapeI16x8, false),
  2581  			)
  2582  		case wasm.OpcodeVecI16x8MaxS:
  2583  			c.emit(
  2584  				NewOperationV128Max(ShapeI16x8, true),
  2585  			)
  2586  		case wasm.OpcodeVecI16x8MaxU:
  2587  			c.emit(
  2588  				NewOperationV128Max(ShapeI16x8, false),
  2589  			)
  2590  		case wasm.OpcodeVecI16x8AvgrU:
  2591  			c.emit(
  2592  				NewOperationV128AvgrU(ShapeI16x8),
  2593  			)
  2594  		case wasm.OpcodeVecI32x4MinS:
  2595  			c.emit(
  2596  				NewOperationV128Min(ShapeI32x4, true),
  2597  			)
  2598  		case wasm.OpcodeVecI32x4MinU:
  2599  			c.emit(
  2600  				NewOperationV128Min(ShapeI32x4, false),
  2601  			)
  2602  		case wasm.OpcodeVecI32x4MaxS:
  2603  			c.emit(
  2604  				NewOperationV128Max(ShapeI32x4, true),
  2605  			)
  2606  		case wasm.OpcodeVecI32x4MaxU:
  2607  			c.emit(
  2608  				NewOperationV128Max(ShapeI32x4, false),
  2609  			)
  2610  		case wasm.OpcodeVecF32x4Min:
  2611  			c.emit(
  2612  				NewOperationV128Min(ShapeF32x4, false),
  2613  			)
  2614  		case wasm.OpcodeVecF32x4Max:
  2615  			c.emit(
  2616  				NewOperationV128Max(ShapeF32x4, false),
  2617  			)
  2618  		case wasm.OpcodeVecF64x2Min:
  2619  			c.emit(
  2620  				NewOperationV128Min(ShapeF64x2, false),
  2621  			)
  2622  		case wasm.OpcodeVecF64x2Max:
  2623  			c.emit(
  2624  				NewOperationV128Max(ShapeF64x2, false),
  2625  			)
  2626  		case wasm.OpcodeVecF32x4Pmin:
  2627  			c.emit(
  2628  				NewOperationV128Pmin(ShapeF32x4),
  2629  			)
  2630  		case wasm.OpcodeVecF32x4Pmax:
  2631  			c.emit(
  2632  				NewOperationV128Pmax(ShapeF32x4),
  2633  			)
  2634  		case wasm.OpcodeVecF64x2Pmin:
  2635  			c.emit(
  2636  				NewOperationV128Pmin(ShapeF64x2),
  2637  			)
  2638  		case wasm.OpcodeVecF64x2Pmax:
  2639  			c.emit(
  2640  				NewOperationV128Pmax(ShapeF64x2),
  2641  			)
  2642  		case wasm.OpcodeVecF32x4Ceil:
  2643  			c.emit(
  2644  				NewOperationV128Ceil(ShapeF32x4),
  2645  			)
  2646  		case wasm.OpcodeVecF32x4Floor:
  2647  			c.emit(
  2648  				NewOperationV128Floor(ShapeF32x4),
  2649  			)
  2650  		case wasm.OpcodeVecF32x4Trunc:
  2651  			c.emit(
  2652  				NewOperationV128Trunc(ShapeF32x4),
  2653  			)
  2654  		case wasm.OpcodeVecF32x4Nearest:
  2655  			c.emit(
  2656  				NewOperationV128Nearest(ShapeF32x4),
  2657  			)
  2658  		case wasm.OpcodeVecF64x2Ceil:
  2659  			c.emit(
  2660  				NewOperationV128Ceil(ShapeF64x2),
  2661  			)
  2662  		case wasm.OpcodeVecF64x2Floor:
  2663  			c.emit(
  2664  				NewOperationV128Floor(ShapeF64x2),
  2665  			)
  2666  		case wasm.OpcodeVecF64x2Trunc:
  2667  			c.emit(
  2668  				NewOperationV128Trunc(ShapeF64x2),
  2669  			)
  2670  		case wasm.OpcodeVecF64x2Nearest:
  2671  			c.emit(
  2672  				NewOperationV128Nearest(ShapeF64x2),
  2673  			)
  2674  		case wasm.OpcodeVecI16x8ExtendLowI8x16S:
  2675  			c.emit(
  2676  				NewOperationV128Extend(ShapeI8x16, true, true),
  2677  			)
  2678  		case wasm.OpcodeVecI16x8ExtendHighI8x16S:
  2679  			c.emit(
  2680  				NewOperationV128Extend(ShapeI8x16, true, false),
  2681  			)
  2682  		case wasm.OpcodeVecI16x8ExtendLowI8x16U:
  2683  			c.emit(
  2684  				NewOperationV128Extend(ShapeI8x16, false, true),
  2685  			)
  2686  		case wasm.OpcodeVecI16x8ExtendHighI8x16U:
  2687  			c.emit(
  2688  				NewOperationV128Extend(ShapeI8x16, false, false),
  2689  			)
  2690  		case wasm.OpcodeVecI32x4ExtendLowI16x8S:
  2691  			c.emit(
  2692  				NewOperationV128Extend(ShapeI16x8, true, true),
  2693  			)
  2694  		case wasm.OpcodeVecI32x4ExtendHighI16x8S:
  2695  			c.emit(
  2696  				NewOperationV128Extend(ShapeI16x8, true, false),
  2697  			)
  2698  		case wasm.OpcodeVecI32x4ExtendLowI16x8U:
  2699  			c.emit(
  2700  				NewOperationV128Extend(ShapeI16x8, false, true),
  2701  			)
  2702  		case wasm.OpcodeVecI32x4ExtendHighI16x8U:
  2703  			c.emit(
  2704  				NewOperationV128Extend(ShapeI16x8, false, false),
  2705  			)
  2706  		case wasm.OpcodeVecI64x2ExtendLowI32x4S:
  2707  			c.emit(
  2708  				NewOperationV128Extend(ShapeI32x4, true, true),
  2709  			)
  2710  		case wasm.OpcodeVecI64x2ExtendHighI32x4S:
  2711  			c.emit(
  2712  				NewOperationV128Extend(ShapeI32x4, true, false),
  2713  			)
  2714  		case wasm.OpcodeVecI64x2ExtendLowI32x4U:
  2715  			c.emit(
  2716  				NewOperationV128Extend(ShapeI32x4, false, true),
  2717  			)
  2718  		case wasm.OpcodeVecI64x2ExtendHighI32x4U:
  2719  			c.emit(
  2720  				NewOperationV128Extend(ShapeI32x4, false, false),
  2721  			)
  2722  		case wasm.OpcodeVecI16x8Q15mulrSatS:
  2723  			c.emit(
  2724  				NewOperationV128Q15mulrSatS(),
  2725  			)
  2726  		case wasm.OpcodeVecI16x8ExtMulLowI8x16S:
  2727  			c.emit(
  2728  				NewOperationV128ExtMul(ShapeI8x16, true, true),
  2729  			)
  2730  		case wasm.OpcodeVecI16x8ExtMulHighI8x16S:
  2731  			c.emit(
  2732  				NewOperationV128ExtMul(ShapeI8x16, true, false),
  2733  			)
  2734  		case wasm.OpcodeVecI16x8ExtMulLowI8x16U:
  2735  			c.emit(
  2736  				NewOperationV128ExtMul(ShapeI8x16, false, true),
  2737  			)
  2738  		case wasm.OpcodeVecI16x8ExtMulHighI8x16U:
  2739  			c.emit(
  2740  				NewOperationV128ExtMul(ShapeI8x16, false, false),
  2741  			)
  2742  		case wasm.OpcodeVecI32x4ExtMulLowI16x8S:
  2743  			c.emit(
  2744  				NewOperationV128ExtMul(ShapeI16x8, true, true),
  2745  			)
  2746  		case wasm.OpcodeVecI32x4ExtMulHighI16x8S:
  2747  			c.emit(
  2748  				NewOperationV128ExtMul(ShapeI16x8, true, false),
  2749  			)
  2750  		case wasm.OpcodeVecI32x4ExtMulLowI16x8U:
  2751  			c.emit(
  2752  				NewOperationV128ExtMul(ShapeI16x8, false, true),
  2753  			)
  2754  		case wasm.OpcodeVecI32x4ExtMulHighI16x8U:
  2755  			c.emit(
  2756  				NewOperationV128ExtMul(ShapeI16x8, false, false),
  2757  			)
  2758  		case wasm.OpcodeVecI64x2ExtMulLowI32x4S:
  2759  			c.emit(
  2760  				NewOperationV128ExtMul(ShapeI32x4, true, true),
  2761  			)
  2762  		case wasm.OpcodeVecI64x2ExtMulHighI32x4S:
  2763  			c.emit(
  2764  				NewOperationV128ExtMul(ShapeI32x4, true, false),
  2765  			)
  2766  		case wasm.OpcodeVecI64x2ExtMulLowI32x4U:
  2767  			c.emit(
  2768  				NewOperationV128ExtMul(ShapeI32x4, false, true),
  2769  			)
  2770  		case wasm.OpcodeVecI64x2ExtMulHighI32x4U:
  2771  			c.emit(
  2772  				NewOperationV128ExtMul(ShapeI32x4, false, false),
  2773  			)
  2774  		case wasm.OpcodeVecI16x8ExtaddPairwiseI8x16S:
  2775  			c.emit(
  2776  				NewOperationV128ExtAddPairwise(ShapeI8x16, true),
  2777  			)
  2778  		case wasm.OpcodeVecI16x8ExtaddPairwiseI8x16U:
  2779  			c.emit(
  2780  				NewOperationV128ExtAddPairwise(ShapeI8x16, false),
  2781  			)
  2782  		case wasm.OpcodeVecI32x4ExtaddPairwiseI16x8S:
  2783  			c.emit(
  2784  				NewOperationV128ExtAddPairwise(ShapeI16x8, true),
  2785  			)
  2786  		case wasm.OpcodeVecI32x4ExtaddPairwiseI16x8U:
  2787  			c.emit(
  2788  				NewOperationV128ExtAddPairwise(ShapeI16x8, false),
  2789  			)
  2790  		case wasm.OpcodeVecF64x2PromoteLowF32x4Zero:
  2791  			c.emit(
  2792  				NewOperationV128FloatPromote(),
  2793  			)
  2794  		case wasm.OpcodeVecF32x4DemoteF64x2Zero:
  2795  			c.emit(
  2796  				NewOperationV128FloatDemote(),
  2797  			)
  2798  		case wasm.OpcodeVecF32x4ConvertI32x4S:
  2799  			c.emit(
  2800  				NewOperationV128FConvertFromI(ShapeF32x4, true),
  2801  			)
  2802  		case wasm.OpcodeVecF32x4ConvertI32x4U:
  2803  			c.emit(
  2804  				NewOperationV128FConvertFromI(ShapeF32x4, false),
  2805  			)
  2806  		case wasm.OpcodeVecF64x2ConvertLowI32x4S:
  2807  			c.emit(
  2808  				NewOperationV128FConvertFromI(ShapeF64x2, true),
  2809  			)
  2810  		case wasm.OpcodeVecF64x2ConvertLowI32x4U:
  2811  			c.emit(
  2812  				NewOperationV128FConvertFromI(ShapeF64x2, false),
  2813  			)
  2814  		case wasm.OpcodeVecI32x4DotI16x8S:
  2815  			c.emit(
  2816  				NewOperationV128Dot(),
  2817  			)
  2818  		case wasm.OpcodeVecI8x16NarrowI16x8S:
  2819  			c.emit(
  2820  				NewOperationV128Narrow(ShapeI16x8, true),
  2821  			)
  2822  		case wasm.OpcodeVecI8x16NarrowI16x8U:
  2823  			c.emit(
  2824  				NewOperationV128Narrow(ShapeI16x8, false),
  2825  			)
  2826  		case wasm.OpcodeVecI16x8NarrowI32x4S:
  2827  			c.emit(
  2828  				NewOperationV128Narrow(ShapeI32x4, true),
  2829  			)
  2830  		case wasm.OpcodeVecI16x8NarrowI32x4U:
  2831  			c.emit(
  2832  				NewOperationV128Narrow(ShapeI32x4, false),
  2833  			)
  2834  		case wasm.OpcodeVecI32x4TruncSatF32x4S:
  2835  			c.emit(
  2836  				NewOperationV128ITruncSatFromF(ShapeF32x4, true),
  2837  			)
  2838  		case wasm.OpcodeVecI32x4TruncSatF32x4U:
  2839  			c.emit(
  2840  				NewOperationV128ITruncSatFromF(ShapeF32x4, false),
  2841  			)
  2842  		case wasm.OpcodeVecI32x4TruncSatF64x2SZero:
  2843  			c.emit(
  2844  				NewOperationV128ITruncSatFromF(ShapeF64x2, true),
  2845  			)
  2846  		case wasm.OpcodeVecI32x4TruncSatF64x2UZero:
  2847  			c.emit(
  2848  				NewOperationV128ITruncSatFromF(ShapeF64x2, false),
  2849  			)
  2850  		default:
  2851  			return fmt.Errorf("unsupported vector instruction in wazeroir: %s", wasm.VectorInstructionName(vecOp))
  2852  		}
  2853  	case wasm.OpcodeAtomicPrefix:
  2854  		c.pc++
  2855  		atomicOp := c.body[c.pc]
  2856  		switch atomicOp {
  2857  		case wasm.OpcodeAtomicMemoryWait32:
  2858  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicMemoryWait32Name)
  2859  			if err != nil {
  2860  				return err
  2861  			}
  2862  			c.emit(
  2863  				NewOperationAtomicMemoryWait(UnsignedTypeI32, imm),
  2864  			)
  2865  		case wasm.OpcodeAtomicMemoryWait64:
  2866  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicMemoryWait64Name)
  2867  			if err != nil {
  2868  				return err
  2869  			}
  2870  			c.emit(
  2871  				NewOperationAtomicMemoryWait(UnsignedTypeI64, imm),
  2872  			)
  2873  		case wasm.OpcodeAtomicMemoryNotify:
  2874  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicMemoryNotifyName)
  2875  			if err != nil {
  2876  				return err
  2877  			}
  2878  			c.emit(
  2879  				NewOperationAtomicMemoryNotify(imm),
  2880  			)
  2881  		case wasm.OpcodeAtomicFence:
  2882  			// Skip immediate value
  2883  			c.pc++
  2884  			_ = c.body[c.pc]
  2885  			c.emit(
  2886  				NewOperationAtomicFence(),
  2887  			)
  2888  		case wasm.OpcodeAtomicI32Load:
  2889  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32LoadName)
  2890  			if err != nil {
  2891  				return err
  2892  			}
  2893  			c.emit(
  2894  				NewOperationAtomicLoad(UnsignedTypeI32, imm),
  2895  			)
  2896  		case wasm.OpcodeAtomicI64Load:
  2897  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64LoadName)
  2898  			if err != nil {
  2899  				return err
  2900  			}
  2901  			c.emit(
  2902  				NewOperationAtomicLoad(UnsignedTypeI64, imm),
  2903  			)
  2904  		case wasm.OpcodeAtomicI32Load8U:
  2905  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Load8UName)
  2906  			if err != nil {
  2907  				return err
  2908  			}
  2909  			c.emit(
  2910  				NewOperationAtomicLoad8(UnsignedTypeI32, imm),
  2911  			)
  2912  		case wasm.OpcodeAtomicI32Load16U:
  2913  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Load16UName)
  2914  			if err != nil {
  2915  				return err
  2916  			}
  2917  			c.emit(
  2918  				NewOperationAtomicLoad16(UnsignedTypeI32, imm),
  2919  			)
  2920  		case wasm.OpcodeAtomicI64Load8U:
  2921  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Load8UName)
  2922  			if err != nil {
  2923  				return err
  2924  			}
  2925  			c.emit(
  2926  				NewOperationAtomicLoad8(UnsignedTypeI64, imm),
  2927  			)
  2928  		case wasm.OpcodeAtomicI64Load16U:
  2929  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Load16UName)
  2930  			if err != nil {
  2931  				return err
  2932  			}
  2933  			c.emit(
  2934  				NewOperationAtomicLoad16(UnsignedTypeI64, imm),
  2935  			)
  2936  		case wasm.OpcodeAtomicI64Load32U:
  2937  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Load32UName)
  2938  			if err != nil {
  2939  				return err
  2940  			}
  2941  			c.emit(
  2942  				NewOperationAtomicLoad(UnsignedTypeI32, imm),
  2943  			)
  2944  		case wasm.OpcodeAtomicI32Store:
  2945  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32StoreName)
  2946  			if err != nil {
  2947  				return err
  2948  			}
  2949  			c.emit(
  2950  				NewOperationAtomicStore(UnsignedTypeI32, imm),
  2951  			)
  2952  		case wasm.OpcodeAtomicI32Store8:
  2953  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Store8Name)
  2954  			if err != nil {
  2955  				return err
  2956  			}
  2957  			c.emit(
  2958  				NewOperationAtomicStore8(UnsignedTypeI32, imm),
  2959  			)
  2960  		case wasm.OpcodeAtomicI32Store16:
  2961  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Store16Name)
  2962  			if err != nil {
  2963  				return err
  2964  			}
  2965  			c.emit(
  2966  				NewOperationAtomicStore16(UnsignedTypeI32, imm),
  2967  			)
  2968  		case wasm.OpcodeAtomicI64Store:
  2969  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64StoreName)
  2970  			if err != nil {
  2971  				return err
  2972  			}
  2973  			c.emit(
  2974  				NewOperationAtomicStore(UnsignedTypeI64, imm),
  2975  			)
  2976  		case wasm.OpcodeAtomicI64Store8:
  2977  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Store8Name)
  2978  			if err != nil {
  2979  				return err
  2980  			}
  2981  			c.emit(
  2982  				NewOperationAtomicStore8(UnsignedTypeI64, imm),
  2983  			)
  2984  		case wasm.OpcodeAtomicI64Store16:
  2985  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Store16Name)
  2986  			if err != nil {
  2987  				return err
  2988  			}
  2989  			c.emit(
  2990  				NewOperationAtomicStore16(UnsignedTypeI64, imm),
  2991  			)
  2992  		case wasm.OpcodeAtomicI64Store32:
  2993  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Store32Name)
  2994  			if err != nil {
  2995  				return err
  2996  			}
  2997  			c.emit(
  2998  				NewOperationAtomicStore(UnsignedTypeI32, imm),
  2999  			)
  3000  		case wasm.OpcodeAtomicI32RmwAdd:
  3001  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32RmwAddName)
  3002  			if err != nil {
  3003  				return err
  3004  			}
  3005  			c.emit(
  3006  				NewOperationAtomicRMW(UnsignedTypeI32, imm, AtomicArithmeticOpAdd),
  3007  			)
  3008  		case wasm.OpcodeAtomicI64RmwAdd:
  3009  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64RmwAddName)
  3010  			if err != nil {
  3011  				return err
  3012  			}
  3013  			c.emit(
  3014  				NewOperationAtomicRMW(UnsignedTypeI64, imm, AtomicArithmeticOpAdd),
  3015  			)
  3016  		case wasm.OpcodeAtomicI32Rmw8AddU:
  3017  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw8AddUName)
  3018  			if err != nil {
  3019  				return err
  3020  			}
  3021  			c.emit(
  3022  				NewOperationAtomicRMW8(UnsignedTypeI32, imm, AtomicArithmeticOpAdd),
  3023  			)
  3024  		case wasm.OpcodeAtomicI64Rmw8AddU:
  3025  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw8AddUName)
  3026  			if err != nil {
  3027  				return err
  3028  			}
  3029  			c.emit(
  3030  				NewOperationAtomicRMW8(UnsignedTypeI64, imm, AtomicArithmeticOpAdd),
  3031  			)
  3032  		case wasm.OpcodeAtomicI32Rmw16AddU:
  3033  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw16AddUName)
  3034  			if err != nil {
  3035  				return err
  3036  			}
  3037  			c.emit(
  3038  				NewOperationAtomicRMW16(UnsignedTypeI32, imm, AtomicArithmeticOpAdd),
  3039  			)
  3040  		case wasm.OpcodeAtomicI64Rmw16AddU:
  3041  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw16AddUName)
  3042  			if err != nil {
  3043  				return err
  3044  			}
  3045  			c.emit(
  3046  				NewOperationAtomicRMW16(UnsignedTypeI64, imm, AtomicArithmeticOpAdd),
  3047  			)
  3048  		case wasm.OpcodeAtomicI64Rmw32AddU:
  3049  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw32AddUName)
  3050  			if err != nil {
  3051  				return err
  3052  			}
  3053  			c.emit(
  3054  				NewOperationAtomicRMW(UnsignedTypeI32, imm, AtomicArithmeticOpAdd),
  3055  			)
  3056  		case wasm.OpcodeAtomicI32RmwSub:
  3057  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32RmwSubName)
  3058  			if err != nil {
  3059  				return err
  3060  			}
  3061  			c.emit(
  3062  				NewOperationAtomicRMW(UnsignedTypeI32, imm, AtomicArithmeticOpSub),
  3063  			)
  3064  		case wasm.OpcodeAtomicI64RmwSub:
  3065  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64RmwSubName)
  3066  			if err != nil {
  3067  				return err
  3068  			}
  3069  			c.emit(
  3070  				NewOperationAtomicRMW(UnsignedTypeI64, imm, AtomicArithmeticOpSub),
  3071  			)
  3072  		case wasm.OpcodeAtomicI32Rmw8SubU:
  3073  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw8SubUName)
  3074  			if err != nil {
  3075  				return err
  3076  			}
  3077  			c.emit(
  3078  				NewOperationAtomicRMW8(UnsignedTypeI32, imm, AtomicArithmeticOpSub),
  3079  			)
  3080  		case wasm.OpcodeAtomicI64Rmw8SubU:
  3081  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw8SubUName)
  3082  			if err != nil {
  3083  				return err
  3084  			}
  3085  			c.emit(
  3086  				NewOperationAtomicRMW8(UnsignedTypeI64, imm, AtomicArithmeticOpSub),
  3087  			)
  3088  		case wasm.OpcodeAtomicI32Rmw16SubU:
  3089  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw16SubUName)
  3090  			if err != nil {
  3091  				return err
  3092  			}
  3093  			c.emit(
  3094  				NewOperationAtomicRMW16(UnsignedTypeI32, imm, AtomicArithmeticOpSub),
  3095  			)
  3096  		case wasm.OpcodeAtomicI64Rmw16SubU:
  3097  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw16SubUName)
  3098  			if err != nil {
  3099  				return err
  3100  			}
  3101  			c.emit(
  3102  				NewOperationAtomicRMW16(UnsignedTypeI64, imm, AtomicArithmeticOpSub),
  3103  			)
  3104  		case wasm.OpcodeAtomicI64Rmw32SubU:
  3105  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw32SubUName)
  3106  			if err != nil {
  3107  				return err
  3108  			}
  3109  			c.emit(
  3110  				NewOperationAtomicRMW(UnsignedTypeI32, imm, AtomicArithmeticOpSub),
  3111  			)
  3112  		case wasm.OpcodeAtomicI32RmwAnd:
  3113  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32RmwAndName)
  3114  			if err != nil {
  3115  				return err
  3116  			}
  3117  			c.emit(
  3118  				NewOperationAtomicRMW(UnsignedTypeI32, imm, AtomicArithmeticOpAnd),
  3119  			)
  3120  		case wasm.OpcodeAtomicI64RmwAnd:
  3121  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64RmwAndName)
  3122  			if err != nil {
  3123  				return err
  3124  			}
  3125  			c.emit(
  3126  				NewOperationAtomicRMW(UnsignedTypeI64, imm, AtomicArithmeticOpAnd),
  3127  			)
  3128  		case wasm.OpcodeAtomicI32Rmw8AndU:
  3129  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw8AndUName)
  3130  			if err != nil {
  3131  				return err
  3132  			}
  3133  			c.emit(
  3134  				NewOperationAtomicRMW8(UnsignedTypeI32, imm, AtomicArithmeticOpAnd),
  3135  			)
  3136  		case wasm.OpcodeAtomicI64Rmw8AndU:
  3137  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw8AndUName)
  3138  			if err != nil {
  3139  				return err
  3140  			}
  3141  			c.emit(
  3142  				NewOperationAtomicRMW8(UnsignedTypeI64, imm, AtomicArithmeticOpAnd),
  3143  			)
  3144  		case wasm.OpcodeAtomicI32Rmw16AndU:
  3145  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw16AndUName)
  3146  			if err != nil {
  3147  				return err
  3148  			}
  3149  			c.emit(
  3150  				NewOperationAtomicRMW16(UnsignedTypeI32, imm, AtomicArithmeticOpAnd),
  3151  			)
  3152  		case wasm.OpcodeAtomicI64Rmw16AndU:
  3153  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw16AndUName)
  3154  			if err != nil {
  3155  				return err
  3156  			}
  3157  			c.emit(
  3158  				NewOperationAtomicRMW16(UnsignedTypeI64, imm, AtomicArithmeticOpAnd),
  3159  			)
  3160  		case wasm.OpcodeAtomicI64Rmw32AndU:
  3161  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw32AndUName)
  3162  			if err != nil {
  3163  				return err
  3164  			}
  3165  			c.emit(
  3166  				NewOperationAtomicRMW(UnsignedTypeI32, imm, AtomicArithmeticOpAnd),
  3167  			)
  3168  		case wasm.OpcodeAtomicI32RmwOr:
  3169  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32RmwOrName)
  3170  			if err != nil {
  3171  				return err
  3172  			}
  3173  			c.emit(
  3174  				NewOperationAtomicRMW(UnsignedTypeI32, imm, AtomicArithmeticOpOr),
  3175  			)
  3176  		case wasm.OpcodeAtomicI64RmwOr:
  3177  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64RmwOrName)
  3178  			if err != nil {
  3179  				return err
  3180  			}
  3181  			c.emit(
  3182  				NewOperationAtomicRMW(UnsignedTypeI64, imm, AtomicArithmeticOpOr),
  3183  			)
  3184  		case wasm.OpcodeAtomicI32Rmw8OrU:
  3185  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw8OrUName)
  3186  			if err != nil {
  3187  				return err
  3188  			}
  3189  			c.emit(
  3190  				NewOperationAtomicRMW8(UnsignedTypeI32, imm, AtomicArithmeticOpOr),
  3191  			)
  3192  		case wasm.OpcodeAtomicI64Rmw8OrU:
  3193  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw8OrUName)
  3194  			if err != nil {
  3195  				return err
  3196  			}
  3197  			c.emit(
  3198  				NewOperationAtomicRMW8(UnsignedTypeI64, imm, AtomicArithmeticOpOr),
  3199  			)
  3200  		case wasm.OpcodeAtomicI32Rmw16OrU:
  3201  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw16OrUName)
  3202  			if err != nil {
  3203  				return err
  3204  			}
  3205  			c.emit(
  3206  				NewOperationAtomicRMW16(UnsignedTypeI32, imm, AtomicArithmeticOpOr),
  3207  			)
  3208  		case wasm.OpcodeAtomicI64Rmw16OrU:
  3209  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw16OrUName)
  3210  			if err != nil {
  3211  				return err
  3212  			}
  3213  			c.emit(
  3214  				NewOperationAtomicRMW16(UnsignedTypeI64, imm, AtomicArithmeticOpOr),
  3215  			)
  3216  		case wasm.OpcodeAtomicI64Rmw32OrU:
  3217  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw32OrUName)
  3218  			if err != nil {
  3219  				return err
  3220  			}
  3221  			c.emit(
  3222  				NewOperationAtomicRMW(UnsignedTypeI32, imm, AtomicArithmeticOpOr),
  3223  			)
  3224  		case wasm.OpcodeAtomicI32RmwXor:
  3225  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32RmwXorName)
  3226  			if err != nil {
  3227  				return err
  3228  			}
  3229  			c.emit(
  3230  				NewOperationAtomicRMW(UnsignedTypeI32, imm, AtomicArithmeticOpXor),
  3231  			)
  3232  		case wasm.OpcodeAtomicI64RmwXor:
  3233  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64RmwXorName)
  3234  			if err != nil {
  3235  				return err
  3236  			}
  3237  			c.emit(
  3238  				NewOperationAtomicRMW(UnsignedTypeI64, imm, AtomicArithmeticOpXor),
  3239  			)
  3240  		case wasm.OpcodeAtomicI32Rmw8XorU:
  3241  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw8XorUName)
  3242  			if err != nil {
  3243  				return err
  3244  			}
  3245  			c.emit(
  3246  				NewOperationAtomicRMW8(UnsignedTypeI32, imm, AtomicArithmeticOpXor),
  3247  			)
  3248  		case wasm.OpcodeAtomicI64Rmw8XorU:
  3249  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw8XorUName)
  3250  			if err != nil {
  3251  				return err
  3252  			}
  3253  			c.emit(
  3254  				NewOperationAtomicRMW8(UnsignedTypeI64, imm, AtomicArithmeticOpXor),
  3255  			)
  3256  		case wasm.OpcodeAtomicI32Rmw16XorU:
  3257  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw16XorUName)
  3258  			if err != nil {
  3259  				return err
  3260  			}
  3261  			c.emit(
  3262  				NewOperationAtomicRMW16(UnsignedTypeI32, imm, AtomicArithmeticOpXor),
  3263  			)
  3264  		case wasm.OpcodeAtomicI64Rmw16XorU:
  3265  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw16XorUName)
  3266  			if err != nil {
  3267  				return err
  3268  			}
  3269  			c.emit(
  3270  				NewOperationAtomicRMW16(UnsignedTypeI64, imm, AtomicArithmeticOpXor),
  3271  			)
  3272  		case wasm.OpcodeAtomicI64Rmw32XorU:
  3273  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw32XorUName)
  3274  			if err != nil {
  3275  				return err
  3276  			}
  3277  			c.emit(
  3278  				NewOperationAtomicRMW(UnsignedTypeI32, imm, AtomicArithmeticOpXor),
  3279  			)
  3280  		case wasm.OpcodeAtomicI32RmwXchg:
  3281  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32RmwXchgName)
  3282  			if err != nil {
  3283  				return err
  3284  			}
  3285  			c.emit(
  3286  				NewOperationAtomicRMW(UnsignedTypeI32, imm, AtomicArithmeticOpNop),
  3287  			)
  3288  		case wasm.OpcodeAtomicI64RmwXchg:
  3289  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64RmwXchgName)
  3290  			if err != nil {
  3291  				return err
  3292  			}
  3293  			c.emit(
  3294  				NewOperationAtomicRMW(UnsignedTypeI64, imm, AtomicArithmeticOpNop),
  3295  			)
  3296  		case wasm.OpcodeAtomicI32Rmw8XchgU:
  3297  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw8XchgUName)
  3298  			if err != nil {
  3299  				return err
  3300  			}
  3301  			c.emit(
  3302  				NewOperationAtomicRMW8(UnsignedTypeI32, imm, AtomicArithmeticOpNop),
  3303  			)
  3304  		case wasm.OpcodeAtomicI64Rmw8XchgU:
  3305  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw8XchgUName)
  3306  			if err != nil {
  3307  				return err
  3308  			}
  3309  			c.emit(
  3310  				NewOperationAtomicRMW8(UnsignedTypeI64, imm, AtomicArithmeticOpNop),
  3311  			)
  3312  		case wasm.OpcodeAtomicI32Rmw16XchgU:
  3313  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw16XchgUName)
  3314  			if err != nil {
  3315  				return err
  3316  			}
  3317  			c.emit(
  3318  				NewOperationAtomicRMW16(UnsignedTypeI32, imm, AtomicArithmeticOpNop),
  3319  			)
  3320  		case wasm.OpcodeAtomicI64Rmw16XchgU:
  3321  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw16XchgUName)
  3322  			if err != nil {
  3323  				return err
  3324  			}
  3325  			c.emit(
  3326  				NewOperationAtomicRMW16(UnsignedTypeI64, imm, AtomicArithmeticOpNop),
  3327  			)
  3328  		case wasm.OpcodeAtomicI64Rmw32XchgU:
  3329  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw32XchgUName)
  3330  			if err != nil {
  3331  				return err
  3332  			}
  3333  			c.emit(
  3334  				NewOperationAtomicRMW(UnsignedTypeI32, imm, AtomicArithmeticOpNop),
  3335  			)
  3336  		case wasm.OpcodeAtomicI32RmwCmpxchg:
  3337  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32RmwCmpxchgName)
  3338  			if err != nil {
  3339  				return err
  3340  			}
  3341  			c.emit(
  3342  				NewOperationAtomicRMWCmpxchg(UnsignedTypeI32, imm),
  3343  			)
  3344  		case wasm.OpcodeAtomicI64RmwCmpxchg:
  3345  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64RmwCmpxchgName)
  3346  			if err != nil {
  3347  				return err
  3348  			}
  3349  			c.emit(
  3350  				NewOperationAtomicRMWCmpxchg(UnsignedTypeI64, imm),
  3351  			)
  3352  		case wasm.OpcodeAtomicI32Rmw8CmpxchgU:
  3353  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw8CmpxchgUName)
  3354  			if err != nil {
  3355  				return err
  3356  			}
  3357  			c.emit(
  3358  				NewOperationAtomicRMW8Cmpxchg(UnsignedTypeI32, imm),
  3359  			)
  3360  		case wasm.OpcodeAtomicI64Rmw8CmpxchgU:
  3361  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw8CmpxchgUName)
  3362  			if err != nil {
  3363  				return err
  3364  			}
  3365  			c.emit(
  3366  				NewOperationAtomicRMW8Cmpxchg(UnsignedTypeI64, imm),
  3367  			)
  3368  		case wasm.OpcodeAtomicI32Rmw16CmpxchgU:
  3369  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw16CmpxchgUName)
  3370  			if err != nil {
  3371  				return err
  3372  			}
  3373  			c.emit(
  3374  				NewOperationAtomicRMW16Cmpxchg(UnsignedTypeI32, imm),
  3375  			)
  3376  		case wasm.OpcodeAtomicI64Rmw16CmpxchgU:
  3377  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw16CmpxchgUName)
  3378  			if err != nil {
  3379  				return err
  3380  			}
  3381  			c.emit(
  3382  				NewOperationAtomicRMW16Cmpxchg(UnsignedTypeI64, imm),
  3383  			)
  3384  		case wasm.OpcodeAtomicI64Rmw32CmpxchgU:
  3385  			imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw32CmpxchgUName)
  3386  			if err != nil {
  3387  				return err
  3388  			}
  3389  			c.emit(
  3390  				NewOperationAtomicRMWCmpxchg(UnsignedTypeI32, imm),
  3391  			)
  3392  		default:
  3393  			return fmt.Errorf("unsupported atomic instruction in wazeroir: %s", wasm.AtomicInstructionName(atomicOp))
  3394  		}
  3395  	default:
  3396  		return fmt.Errorf("unsupported instruction in wazeroir: 0x%x", op)
  3397  	}
  3398  
  3399  	// Move the program counter to point to the next instruction.
  3400  	c.pc++
  3401  	return nil
  3402  }
  3403  
  3404  func (c *Compiler) nextFrameID() (id uint32) {
  3405  	id = c.currentFrameID + 1
  3406  	c.currentFrameID++
  3407  	return
  3408  }
  3409  
  3410  func (c *Compiler) applyToStack(opcode wasm.Opcode) (index uint32, err error) {
  3411  	switch opcode {
  3412  	case
  3413  		// These are the opcodes that is coupled with "index" immediate
  3414  		// and it DOES affect the signature of opcode.
  3415  		wasm.OpcodeCall,
  3416  		wasm.OpcodeCallIndirect,
  3417  		wasm.OpcodeLocalGet,
  3418  		wasm.OpcodeLocalSet,
  3419  		wasm.OpcodeLocalTee,
  3420  		wasm.OpcodeGlobalGet,
  3421  		wasm.OpcodeGlobalSet:
  3422  		// Assumes that we are at the opcode now so skip it before read immediates.
  3423  		v, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  3424  		if err != nil {
  3425  			return 0, fmt.Errorf("reading immediates: %w", err)
  3426  		}
  3427  		c.pc += num
  3428  		index = v
  3429  	default:
  3430  		// Note that other opcodes are free of index
  3431  		// as it doesn't affect the signature of opt code.
  3432  		// In other words, the "index" argument of wasmOpcodeSignature
  3433  		// is ignored there.
  3434  	}
  3435  
  3436  	if c.unreachableState.on {
  3437  		return 0, nil
  3438  	}
  3439  
  3440  	// Retrieve the signature of the opcode.
  3441  	s, err := c.wasmOpcodeSignature(opcode, index)
  3442  	if err != nil {
  3443  		return 0, err
  3444  	}
  3445  
  3446  	// Manipulate the stack according to the signature.
  3447  	// Note that the following algorithm assumes that
  3448  	// the unknown type is unique in the signature,
  3449  	// and is determined by the actual type on the stack.
  3450  	// The determined type is stored in this typeParam.
  3451  	var typeParam UnsignedType
  3452  	var typeParamFound bool
  3453  	for i := range s.in {
  3454  		want := s.in[len(s.in)-1-i]
  3455  		actual := c.stackPop()
  3456  		if want == UnsignedTypeUnknown && typeParamFound {
  3457  			want = typeParam
  3458  		} else if want == UnsignedTypeUnknown {
  3459  			want = actual
  3460  			typeParam = want
  3461  			typeParamFound = true
  3462  		}
  3463  		if want != actual {
  3464  			return 0, fmt.Errorf("input signature mismatch: want %s but have %s", want, actual)
  3465  		}
  3466  	}
  3467  
  3468  	for _, target := range s.out {
  3469  		if target == UnsignedTypeUnknown && !typeParamFound {
  3470  			return 0, fmt.Errorf("cannot determine type of unknown result")
  3471  		} else if target == UnsignedTypeUnknown {
  3472  			c.stackPush(typeParam)
  3473  		} else {
  3474  			c.stackPush(target)
  3475  		}
  3476  	}
  3477  
  3478  	return index, nil
  3479  }
  3480  
  3481  func (c *Compiler) stackPeek() (ret UnsignedType) {
  3482  	ret = c.stack[len(c.stack)-1]
  3483  	return
  3484  }
  3485  
  3486  func (c *Compiler) stackPop() (ret UnsignedType) {
  3487  	// No need to check stack bound
  3488  	// as we can assume that all the operations
  3489  	// are valid thanks to validateFunction
  3490  	// at module validation phase.
  3491  	ret = c.stack[len(c.stack)-1]
  3492  	c.stack = c.stack[:len(c.stack)-1]
  3493  	return
  3494  }
  3495  
  3496  func (c *Compiler) stackPush(ts UnsignedType) {
  3497  	c.stack = append(c.stack, ts)
  3498  }
  3499  
  3500  // emit adds the operations into the result.
  3501  func (c *Compiler) emit(op UnionOperation) {
  3502  	if !c.unreachableState.on {
  3503  		switch op.Kind {
  3504  		case OperationKindDrop:
  3505  			// If the drop range is nil,
  3506  			// we could remove such operations.
  3507  			// That happens when drop operation is unnecessary.
  3508  			// i.e. when there's no need to adjust stack before jmp.
  3509  			if int64(op.U1) == -1 {
  3510  				return
  3511  			}
  3512  		}
  3513  		c.result.Operations = append(c.result.Operations, op)
  3514  		if c.needSourceOffset {
  3515  			c.result.IROperationSourceOffsetsInWasmBinary = append(c.result.IROperationSourceOffsetsInWasmBinary,
  3516  				c.currentOpPC+c.bodyOffsetInCodeSection)
  3517  		}
  3518  	}
  3519  }
  3520  
  3521  // Emit const expression with default values of the given type.
  3522  func (c *Compiler) emitDefaultValue(t wasm.ValueType) {
  3523  	switch t {
  3524  	case wasm.ValueTypeI32:
  3525  		c.stackPush(UnsignedTypeI32)
  3526  		c.emit(NewOperationConstI32(0))
  3527  	case wasm.ValueTypeI64, wasm.ValueTypeExternref, wasm.ValueTypeFuncref:
  3528  		c.stackPush(UnsignedTypeI64)
  3529  		c.emit(NewOperationConstI64(0))
  3530  	case wasm.ValueTypeF32:
  3531  		c.stackPush(UnsignedTypeF32)
  3532  		c.emit(NewOperationConstF32(0))
  3533  	case wasm.ValueTypeF64:
  3534  		c.stackPush(UnsignedTypeF64)
  3535  		c.emit(NewOperationConstF64(0))
  3536  	case wasm.ValueTypeV128:
  3537  		c.stackPush(UnsignedTypeV128)
  3538  		c.emit(NewOperationV128Const(0, 0))
  3539  	}
  3540  }
  3541  
  3542  // Returns the "depth" (starting from top of the stack)
  3543  // of the n-th local.
  3544  func (c *Compiler) localDepth(index wasm.Index) int {
  3545  	height := c.localIndexToStackHeightInUint64[index]
  3546  	return c.stackLenInUint64(len(c.stack)) - 1 - int(height)
  3547  }
  3548  
  3549  func (c *Compiler) localType(index wasm.Index) (t wasm.ValueType) {
  3550  	if params := uint32(len(c.sig.Params)); index < params {
  3551  		t = c.sig.Params[index]
  3552  	} else {
  3553  		t = c.localTypes[index-params]
  3554  	}
  3555  	return
  3556  }
  3557  
  3558  // getFrameDropRange returns the range (starting from top of the stack) that spans across the (uint64) stack. The range is
  3559  // supposed to be dropped from the stack when the given frame exists or branch into it.
  3560  //
  3561  // * frame is the control frame which the call-site is trying to branch into or exit.
  3562  // * isEnd true if the call-site is handling wasm.OpcodeEnd.
  3563  func (c *Compiler) getFrameDropRange(frame *controlFrame, isEnd bool) InclusiveRange {
  3564  	var start int
  3565  	if !isEnd && frame.kind == controlFrameKindLoop {
  3566  		// If this is not End and the call-site is trying to branch into the Loop control frame,
  3567  		// we have to Start executing from the beginning of the loop block.
  3568  		// Therefore, we have to pass the inputs to the frame.
  3569  		start = frame.blockType.ParamNumInUint64
  3570  	} else {
  3571  		start = frame.blockType.ResultNumInUint64
  3572  	}
  3573  	var end int
  3574  	if frame.kind == controlFrameKindFunction {
  3575  		// On the function return, we eliminate all the contents on the stack
  3576  		// including locals (existing below of frame.originalStackLen)
  3577  		end = c.stackLenInUint64(len(c.stack)) - 1
  3578  	} else {
  3579  		end = c.stackLenInUint64(len(c.stack)) - 1 - c.stackLenInUint64(frame.originalStackLenWithoutParam)
  3580  	}
  3581  	if start <= end {
  3582  		return InclusiveRange{Start: int32(start), End: int32(end)}
  3583  	} else {
  3584  		return NopInclusiveRange
  3585  	}
  3586  }
  3587  
  3588  func (c *Compiler) stackLenInUint64(ceil int) (ret int) {
  3589  	for i := 0; i < ceil; i++ {
  3590  		if c.stack[i] == UnsignedTypeV128 {
  3591  			ret += 2
  3592  		} else {
  3593  			ret++
  3594  		}
  3595  	}
  3596  	return
  3597  }
  3598  
  3599  func (c *Compiler) readMemoryArg(tag string) (MemoryArg, error) {
  3600  	c.result.UsesMemory = true
  3601  	alignment, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  3602  	if err != nil {
  3603  		return MemoryArg{}, fmt.Errorf("reading alignment for %s: %w", tag, err)
  3604  	}
  3605  	c.pc += num
  3606  	offset, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  3607  	if err != nil {
  3608  		return MemoryArg{}, fmt.Errorf("reading offset for %s: %w", tag, err)
  3609  	}
  3610  	c.pc += num
  3611  	return MemoryArg{Offset: offset, Alignment: alignment}, nil
  3612  }