...

Source file src/github.com/tetratelabs/wazero/internal/wazeroir/compiler.go

Documentation: github.com/tetratelabs/wazero/internal/wazeroir

     1  package wazeroir
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"fmt"
     7  	"math"
     8  	"strings"
     9  
    10  	"github.com/tetratelabs/wazero/api"
    11  	"github.com/tetratelabs/wazero/internal/leb128"
    12  	"github.com/tetratelabs/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.OpcodeMiscPrefix {
   381  			instName = wasm.MiscInstructionName(c.body[c.pc+1])
   382  		} else {
   383  			instName = wasm.InstructionName(op)
   384  		}
   385  		fmt.Printf("handling %s, unreachable_state(on=%v,depth=%d), stack=%v\n",
   386  			instName, c.unreachableState.on, c.unreachableState.depth, c.stack,
   387  		)
   388  	}
   389  
   390  	var peekValueType UnsignedType
   391  	if len(c.stack) > 0 {
   392  		peekValueType = c.stackPeek()
   393  	}
   394  
   395  	// Modify the stack according the current instruction.
   396  	// Note that some instructions will read "index" in
   397  	// applyToStack and advance c.pc inside the function.
   398  	index, err := c.applyToStack(op)
   399  	if err != nil {
   400  		return fmt.Errorf("apply stack failed for %s: %w", wasm.InstructionName(op), err)
   401  	}
   402  	// Now we handle each instruction, and
   403  	// emit the corresponding wazeroir operations to the results.
   404  operatorSwitch:
   405  	switch op {
   406  	case wasm.OpcodeUnreachable:
   407  		c.emit(NewOperationUnreachable())
   408  		c.markUnreachable()
   409  	case wasm.OpcodeNop:
   410  		// Nop is noop!
   411  	case wasm.OpcodeBlock:
   412  		c.br.Reset(c.body[c.pc+1:])
   413  		bt, num, err := wasm.DecodeBlockType(c.types, c.br, c.enabledFeatures)
   414  		if err != nil {
   415  			return fmt.Errorf("reading block type for block instruction: %w", err)
   416  		}
   417  		c.pc += num
   418  
   419  		if c.unreachableState.on {
   420  			// If it is currently in unreachable,
   421  			// just remove the entire block.
   422  			c.unreachableState.depth++
   423  			break operatorSwitch
   424  		}
   425  
   426  		// Create a new frame -- entering this block.
   427  		frame := controlFrame{
   428  			frameID:                      c.nextFrameID(),
   429  			originalStackLenWithoutParam: len(c.stack) - len(bt.Params),
   430  			kind:                         controlFrameKindBlockWithoutContinuationLabel,
   431  			blockType:                    bt,
   432  		}
   433  		c.controlFrames.push(frame)
   434  
   435  	case wasm.OpcodeLoop:
   436  		c.br.Reset(c.body[c.pc+1:])
   437  		bt, num, err := wasm.DecodeBlockType(c.types, c.br, c.enabledFeatures)
   438  		if err != nil {
   439  			return fmt.Errorf("reading block type for loop instruction: %w", err)
   440  		}
   441  		c.pc += num
   442  
   443  		if c.unreachableState.on {
   444  			// If it is currently in unreachable,
   445  			// just remove the entire block.
   446  			c.unreachableState.depth++
   447  			break operatorSwitch
   448  		}
   449  
   450  		// Create a new frame -- entering loop.
   451  		frame := controlFrame{
   452  			frameID:                      c.nextFrameID(),
   453  			originalStackLenWithoutParam: len(c.stack) - len(bt.Params),
   454  			kind:                         controlFrameKindLoop,
   455  			blockType:                    bt,
   456  		}
   457  		c.controlFrames.push(frame)
   458  
   459  		// Prep labels for inside and the continuation of this loop.
   460  		loopLabel := NewLabel(LabelKindHeader, frame.frameID)
   461  		c.result.LabelCallers[loopLabel]++
   462  
   463  		// Emit the branch operation to enter inside the loop.
   464  		c.emit(NewOperationBr(loopLabel))
   465  		c.emit(NewOperationLabel(loopLabel))
   466  
   467  		// Insert the exit code check on the loop header, which is the only necessary point in the function body
   468  		// to prevent infinite loop.
   469  		//
   470  		// Note that this is a little aggressive: this checks the exit code regardless the loop header is actually
   471  		// the loop. In other words, this checks even when no br/br_if/br_table instructions jumping to this loop
   472  		// exist. However, in reality, that shouldn't be an issue since such "noop" loop header will highly likely be
   473  		// optimized out by almost all guest language compilers which have the control flow optimization passes.
   474  		if c.ensureTermination {
   475  			c.emit(NewOperationBuiltinFunctionCheckExitCode())
   476  		}
   477  	case wasm.OpcodeIf:
   478  		c.br.Reset(c.body[c.pc+1:])
   479  		bt, num, err := wasm.DecodeBlockType(c.types, c.br, c.enabledFeatures)
   480  		if err != nil {
   481  			return fmt.Errorf("reading block type for if instruction: %w", err)
   482  		}
   483  		c.pc += num
   484  
   485  		if c.unreachableState.on {
   486  			// If it is currently in unreachable,
   487  			// just remove the entire block.
   488  			c.unreachableState.depth++
   489  			break operatorSwitch
   490  		}
   491  
   492  		// Create a new frame -- entering if.
   493  		frame := controlFrame{
   494  			frameID:                      c.nextFrameID(),
   495  			originalStackLenWithoutParam: len(c.stack) - len(bt.Params),
   496  			// Note this will be set to controlFrameKindIfWithElse
   497  			// when else opcode found later.
   498  			kind:      controlFrameKindIfWithoutElse,
   499  			blockType: bt,
   500  		}
   501  		c.controlFrames.push(frame)
   502  
   503  		// Prep labels for if and else of this if.
   504  		thenLabel := NewLabel(LabelKindHeader, frame.frameID)
   505  		elseLabel := NewLabel(LabelKindElse, frame.frameID)
   506  		c.result.LabelCallers[thenLabel]++
   507  		c.result.LabelCallers[elseLabel]++
   508  
   509  		// Emit the branch operation to enter the then block.
   510  		c.emit(NewOperationBrIf(thenLabel, elseLabel, NopInclusiveRange))
   511  		c.emit(NewOperationLabel(thenLabel))
   512  	case wasm.OpcodeElse:
   513  		frame := c.controlFrames.top()
   514  		if c.unreachableState.on && c.unreachableState.depth > 0 {
   515  			// If it is currently in unreachable, and the nested if,
   516  			// just remove the entire else block.
   517  			break operatorSwitch
   518  		} else if c.unreachableState.on {
   519  			// If it is currently in unreachable, and the non-nested if,
   520  			// reset the stack so we can correctly handle the else block.
   521  			top := c.controlFrames.top()
   522  			c.stack = c.stack[:top.originalStackLenWithoutParam]
   523  			top.kind = controlFrameKindIfWithElse
   524  
   525  			// Re-push the parameters to the if block so that else block can use them.
   526  			for _, t := range frame.blockType.Params {
   527  				c.stackPush(wasmValueTypeToUnsignedType(t))
   528  			}
   529  
   530  			// We are no longer unreachable in else frame,
   531  			// so emit the correct label, and reset the unreachable state.
   532  			elseLabel := NewLabel(LabelKindElse, frame.frameID)
   533  			c.resetUnreachable()
   534  			c.emit(
   535  				NewOperationLabel(elseLabel),
   536  			)
   537  			break operatorSwitch
   538  		}
   539  
   540  		// Change the Kind of this If block, indicating that
   541  		// the if has else block.
   542  		frame.kind = controlFrameKindIfWithElse
   543  
   544  		// We need to reset the stack so that
   545  		// the values pushed inside the then block
   546  		// do not affect the else block.
   547  		dropOp := NewOperationDrop(c.getFrameDropRange(frame, false))
   548  
   549  		// Reset the stack manipulated by the then block, and re-push the block param types to the stack.
   550  
   551  		c.stack = c.stack[:frame.originalStackLenWithoutParam]
   552  		for _, t := range frame.blockType.Params {
   553  			c.stackPush(wasmValueTypeToUnsignedType(t))
   554  		}
   555  
   556  		// Prep labels for else and the continuation of this if block.
   557  		elseLabel := NewLabel(LabelKindElse, frame.frameID)
   558  		continuationLabel := NewLabel(LabelKindContinuation, frame.frameID)
   559  		c.result.LabelCallers[continuationLabel]++
   560  
   561  		// Emit the instructions for exiting the if loop,
   562  		// and then the initiation of else block.
   563  		c.emit(dropOp)
   564  		// Jump to the continuation of this block.
   565  		c.emit(NewOperationBr(continuationLabel))
   566  		// Initiate the else block.
   567  		c.emit(NewOperationLabel(elseLabel))
   568  	case wasm.OpcodeEnd:
   569  		if c.unreachableState.on && c.unreachableState.depth > 0 {
   570  			c.unreachableState.depth--
   571  			break operatorSwitch
   572  		} else if c.unreachableState.on {
   573  			c.resetUnreachable()
   574  
   575  			frame := c.controlFrames.pop()
   576  			if c.controlFrames.empty() {
   577  				return nil
   578  			}
   579  
   580  			c.stack = c.stack[:frame.originalStackLenWithoutParam]
   581  			for _, t := range frame.blockType.Results {
   582  				c.stackPush(wasmValueTypeToUnsignedType(t))
   583  			}
   584  
   585  			continuationLabel := NewLabel(LabelKindContinuation, frame.frameID)
   586  			if frame.kind == controlFrameKindIfWithoutElse {
   587  				// Emit the else label.
   588  				elseLabel := NewLabel(LabelKindElse, frame.frameID)
   589  				c.result.LabelCallers[continuationLabel]++
   590  				c.emit(NewOperationLabel(elseLabel))
   591  				c.emit(NewOperationBr(continuationLabel))
   592  				c.emit(NewOperationLabel(continuationLabel))
   593  			} else {
   594  				c.emit(
   595  					NewOperationLabel(continuationLabel),
   596  				)
   597  			}
   598  
   599  			break operatorSwitch
   600  		}
   601  
   602  		frame := c.controlFrames.pop()
   603  
   604  		// We need to reset the stack so that
   605  		// the values pushed inside the block.
   606  		dropOp := NewOperationDrop(c.getFrameDropRange(frame, true))
   607  		c.stack = c.stack[:frame.originalStackLenWithoutParam]
   608  
   609  		// Push the result types onto the stack.
   610  		for _, t := range frame.blockType.Results {
   611  			c.stackPush(wasmValueTypeToUnsignedType(t))
   612  		}
   613  
   614  		// Emit the instructions according to the Kind of the current control frame.
   615  		switch frame.kind {
   616  		case controlFrameKindFunction:
   617  			if !c.controlFrames.empty() {
   618  				// Should never happen. If so, there's a bug in the translation.
   619  				panic("bug: found more function control frames")
   620  			}
   621  			// Return from function.
   622  			c.emit(dropOp)
   623  			c.emit(NewOperationBr(NewLabel(LabelKindReturn, 0)))
   624  		case controlFrameKindIfWithoutElse:
   625  			// This case we have to emit "empty" else label.
   626  			elseLabel := NewLabel(LabelKindElse, frame.frameID)
   627  			continuationLabel := NewLabel(LabelKindContinuation, frame.frameID)
   628  			c.result.LabelCallers[continuationLabel] += 2
   629  			c.emit(dropOp)
   630  			c.emit(NewOperationBr(continuationLabel))
   631  			// Emit the else which soon branches into the continuation.
   632  			c.emit(NewOperationLabel(elseLabel))
   633  			c.emit(NewOperationBr(continuationLabel))
   634  			// Initiate the continuation.
   635  			c.emit(NewOperationLabel(continuationLabel))
   636  		case controlFrameKindBlockWithContinuationLabel,
   637  			controlFrameKindIfWithElse:
   638  			continuationLabel := NewLabel(LabelKindContinuation, frame.frameID)
   639  			c.result.LabelCallers[continuationLabel]++
   640  			c.emit(dropOp)
   641  			c.emit(NewOperationBr(continuationLabel))
   642  			c.emit(NewOperationLabel(continuationLabel))
   643  		case controlFrameKindLoop, controlFrameKindBlockWithoutContinuationLabel:
   644  			c.emit(
   645  				dropOp,
   646  			)
   647  		default:
   648  			// Should never happen. If so, there's a bug in the translation.
   649  			panic(fmt.Errorf("bug: invalid control frame Kind: 0x%x", frame.kind))
   650  		}
   651  
   652  	case wasm.OpcodeBr:
   653  		targetIndex, n, err := leb128.LoadUint32(c.body[c.pc+1:])
   654  		if err != nil {
   655  			return fmt.Errorf("read the target for br_if: %w", err)
   656  		}
   657  		c.pc += n
   658  
   659  		if c.unreachableState.on {
   660  			// If it is currently in unreachable, br is no-op.
   661  			break operatorSwitch
   662  		}
   663  
   664  		targetFrame := c.controlFrames.get(int(targetIndex))
   665  		targetFrame.ensureContinuation()
   666  		dropOp := NewOperationDrop(c.getFrameDropRange(targetFrame, false))
   667  		targetID := targetFrame.asLabel()
   668  		c.result.LabelCallers[targetID]++
   669  		c.emit(dropOp)
   670  		c.emit(NewOperationBr(targetID))
   671  		// Br operation is stack-polymorphic, and mark the state as unreachable.
   672  		// That means subsequent instructions in the current control frame are "unreachable"
   673  		// and can be safely removed.
   674  		c.markUnreachable()
   675  	case wasm.OpcodeBrIf:
   676  		targetIndex, n, err := leb128.LoadUint32(c.body[c.pc+1:])
   677  		if err != nil {
   678  			return fmt.Errorf("read the target for br_if: %w", err)
   679  		}
   680  		c.pc += n
   681  
   682  		if c.unreachableState.on {
   683  			// If it is currently in unreachable, br-if is no-op.
   684  			break operatorSwitch
   685  		}
   686  
   687  		targetFrame := c.controlFrames.get(int(targetIndex))
   688  		targetFrame.ensureContinuation()
   689  		drop := c.getFrameDropRange(targetFrame, false)
   690  		target := targetFrame.asLabel()
   691  		c.result.LabelCallers[target]++
   692  
   693  		continuationLabel := NewLabel(LabelKindHeader, c.nextFrameID())
   694  		c.result.LabelCallers[continuationLabel]++
   695  		c.emit(NewOperationBrIf(target, continuationLabel, drop))
   696  		// Start emitting else block operations.
   697  		c.emit(NewOperationLabel(continuationLabel))
   698  	case wasm.OpcodeBrTable:
   699  		c.br.Reset(c.body[c.pc+1:])
   700  		r := c.br
   701  		numTargets, n, err := leb128.DecodeUint32(r)
   702  		if err != nil {
   703  			return fmt.Errorf("error reading number of targets in br_table: %w", err)
   704  		}
   705  		c.pc += n
   706  
   707  		if c.unreachableState.on {
   708  			// If it is currently in unreachable, br_table is no-op.
   709  			// But before proceeding to the next instruction, we must advance the pc
   710  			// according to the number of br_table targets.
   711  			for i := uint32(0); i <= numTargets; i++ { // inclusive as we also need to read the index of default target.
   712  				_, n, err := leb128.DecodeUint32(r)
   713  				if err != nil {
   714  					return fmt.Errorf("error reading target %d in br_table: %w", i, err)
   715  				}
   716  				c.pc += n
   717  			}
   718  			break operatorSwitch
   719  		}
   720  
   721  		// Read the branch targets.
   722  		s := numTargets * 2
   723  		targetLabels := make([]uint64, 2+s) // (label, InclusiveRange) * (default+numTargets)
   724  		for i := uint32(0); i < s; i += 2 {
   725  			l, n, err := leb128.DecodeUint32(r)
   726  			if err != nil {
   727  				return fmt.Errorf("error reading target %d in br_table: %w", i, err)
   728  			}
   729  			c.pc += n
   730  			targetFrame := c.controlFrames.get(int(l))
   731  			targetFrame.ensureContinuation()
   732  			drop := c.getFrameDropRange(targetFrame, false)
   733  			targetLabel := targetFrame.asLabel()
   734  			targetLabels[i] = uint64(targetLabel)
   735  			targetLabels[i+1] = drop.AsU64()
   736  			c.result.LabelCallers[targetLabel]++
   737  		}
   738  
   739  		// Prep default target control frame.
   740  		l, n, err := leb128.DecodeUint32(r)
   741  		if err != nil {
   742  			return fmt.Errorf("error reading default target of br_table: %w", err)
   743  		}
   744  		c.pc += n
   745  		defaultTargetFrame := c.controlFrames.get(int(l))
   746  		defaultTargetFrame.ensureContinuation()
   747  		defaultTargetDrop := c.getFrameDropRange(defaultTargetFrame, false)
   748  		defaultLabel := defaultTargetFrame.asLabel()
   749  		c.result.LabelCallers[defaultLabel]++
   750  		targetLabels[s] = uint64(defaultLabel)
   751  		targetLabels[s+1] = defaultTargetDrop.AsU64()
   752  		c.emit(NewOperationBrTable(targetLabels))
   753  
   754  		// br_table operation is stack-polymorphic, and mark the state as unreachable.
   755  		// That means subsequent instructions in the current control frame are "unreachable"
   756  		// and can be safely removed.
   757  		c.markUnreachable()
   758  	case wasm.OpcodeReturn:
   759  		functionFrame := c.controlFrames.functionFrame()
   760  		dropOp := NewOperationDrop(c.getFrameDropRange(functionFrame, false))
   761  
   762  		// Cleanup the stack and then jmp to function frame's continuation (meaning return).
   763  		c.emit(dropOp)
   764  		c.emit(NewOperationBr(functionFrame.asLabel()))
   765  
   766  		// Return operation is stack-polymorphic, and mark the state as unreachable.
   767  		// That means subsequent instructions in the current control frame are "unreachable"
   768  		// and can be safely removed.
   769  		c.markUnreachable()
   770  	case wasm.OpcodeCall:
   771  		c.emit(
   772  			NewOperationCall(index),
   773  		)
   774  	case wasm.OpcodeCallIndirect:
   775  		typeIndex := index
   776  		tableIndex, n, err := leb128.LoadUint32(c.body[c.pc+1:])
   777  		if err != nil {
   778  			return fmt.Errorf("read target for br_table: %w", err)
   779  		}
   780  		c.pc += n
   781  		c.emit(
   782  			NewOperationCallIndirect(typeIndex, tableIndex),
   783  		)
   784  	case wasm.OpcodeDrop:
   785  		r := InclusiveRange{Start: 0, End: 0}
   786  		if peekValueType == UnsignedTypeV128 {
   787  			// InclusiveRange is the range in uint64 representation, so dropping a vector value on top
   788  			// should be translated as drop [0..1] inclusively.
   789  			r.End++
   790  		}
   791  		c.emit(NewOperationDrop(r))
   792  	case wasm.OpcodeSelect:
   793  		// If it is on the unreachable state, ignore the instruction.
   794  		if c.unreachableState.on {
   795  			break operatorSwitch
   796  		}
   797  		isTargetVector := c.stackPeek() == UnsignedTypeV128
   798  		c.emit(
   799  			NewOperationSelect(isTargetVector),
   800  		)
   801  	case wasm.OpcodeTypedSelect:
   802  		// Skips two bytes: vector size fixed to 1, and the value type for select.
   803  		c.pc += 2
   804  		// If it is on the unreachable state, ignore the instruction.
   805  		if c.unreachableState.on {
   806  			break operatorSwitch
   807  		}
   808  		// Typed select is semantically equivalent to select at runtime.
   809  		isTargetVector := c.stackPeek() == UnsignedTypeV128
   810  		c.emit(
   811  			NewOperationSelect(isTargetVector),
   812  		)
   813  	case wasm.OpcodeLocalGet:
   814  		depth := c.localDepth(index)
   815  		if isVector := c.localType(index) == wasm.ValueTypeV128; !isVector {
   816  			c.emit(
   817  				// -1 because we already manipulated the stack before
   818  				// called localDepth ^^.
   819  				NewOperationPick(depth-1, isVector),
   820  			)
   821  		} else {
   822  			c.emit(
   823  				// -2 because we already manipulated the stack before
   824  				// called localDepth ^^.
   825  				NewOperationPick(depth-2, isVector),
   826  			)
   827  		}
   828  	case wasm.OpcodeLocalSet:
   829  		depth := c.localDepth(index)
   830  
   831  		isVector := c.localType(index) == wasm.ValueTypeV128
   832  		if isVector {
   833  			c.emit(
   834  				// +2 because we already popped the operands for this operation from the c.stack before
   835  				// called localDepth ^^,
   836  				NewOperationSet(depth+2, isVector),
   837  			)
   838  		} else {
   839  			c.emit(
   840  				// +1 because we already popped the operands for this operation from the c.stack before
   841  				// called localDepth ^^,
   842  				NewOperationSet(depth+1, isVector),
   843  			)
   844  		}
   845  	case wasm.OpcodeLocalTee:
   846  		depth := c.localDepth(index)
   847  		isVector := c.localType(index) == wasm.ValueTypeV128
   848  		if isVector {
   849  			c.emit(NewOperationPick(1, isVector))
   850  			c.emit(NewOperationSet(depth+2, isVector))
   851  		} else {
   852  			c.emit(
   853  				NewOperationPick(0, isVector))
   854  			c.emit(NewOperationSet(depth+1, isVector))
   855  		}
   856  	case wasm.OpcodeGlobalGet:
   857  		c.emit(
   858  			NewOperationGlobalGet(index),
   859  		)
   860  	case wasm.OpcodeGlobalSet:
   861  		c.emit(
   862  			NewOperationGlobalSet(index),
   863  		)
   864  	case wasm.OpcodeI32Load:
   865  		imm, err := c.readMemoryArg(wasm.OpcodeI32LoadName)
   866  		if err != nil {
   867  			return err
   868  		}
   869  		c.emit(NewOperationLoad(UnsignedTypeI32, imm))
   870  	case wasm.OpcodeI64Load:
   871  		imm, err := c.readMemoryArg(wasm.OpcodeI64LoadName)
   872  		if err != nil {
   873  			return err
   874  		}
   875  		c.emit(NewOperationLoad(UnsignedTypeI64, imm))
   876  	case wasm.OpcodeF32Load:
   877  		imm, err := c.readMemoryArg(wasm.OpcodeF32LoadName)
   878  		if err != nil {
   879  			return err
   880  		}
   881  		c.emit(NewOperationLoad(UnsignedTypeF32, imm))
   882  	case wasm.OpcodeF64Load:
   883  		imm, err := c.readMemoryArg(wasm.OpcodeF64LoadName)
   884  		if err != nil {
   885  			return err
   886  		}
   887  		c.emit(NewOperationLoad(UnsignedTypeF64, imm))
   888  	case wasm.OpcodeI32Load8S:
   889  		imm, err := c.readMemoryArg(wasm.OpcodeI32Load8SName)
   890  		if err != nil {
   891  			return err
   892  		}
   893  		c.emit(NewOperationLoad8(SignedInt32, imm))
   894  	case wasm.OpcodeI32Load8U:
   895  		imm, err := c.readMemoryArg(wasm.OpcodeI32Load8UName)
   896  		if err != nil {
   897  			return err
   898  		}
   899  		c.emit(NewOperationLoad8(SignedUint32, imm))
   900  	case wasm.OpcodeI32Load16S:
   901  		imm, err := c.readMemoryArg(wasm.OpcodeI32Load16SName)
   902  		if err != nil {
   903  			return err
   904  		}
   905  		c.emit(NewOperationLoad16(SignedInt32, imm))
   906  	case wasm.OpcodeI32Load16U:
   907  		imm, err := c.readMemoryArg(wasm.OpcodeI32Load16UName)
   908  		if err != nil {
   909  			return err
   910  		}
   911  		c.emit(NewOperationLoad16(SignedUint32, imm))
   912  	case wasm.OpcodeI64Load8S:
   913  		imm, err := c.readMemoryArg(wasm.OpcodeI64Load8SName)
   914  		if err != nil {
   915  			return err
   916  		}
   917  		c.emit(NewOperationLoad8(SignedInt64, imm))
   918  	case wasm.OpcodeI64Load8U:
   919  		imm, err := c.readMemoryArg(wasm.OpcodeI64Load8UName)
   920  		if err != nil {
   921  			return err
   922  		}
   923  		c.emit(NewOperationLoad8(SignedUint64, imm))
   924  	case wasm.OpcodeI64Load16S:
   925  		imm, err := c.readMemoryArg(wasm.OpcodeI64Load16SName)
   926  		if err != nil {
   927  			return err
   928  		}
   929  		c.emit(NewOperationLoad16(SignedInt64, imm))
   930  	case wasm.OpcodeI64Load16U:
   931  		imm, err := c.readMemoryArg(wasm.OpcodeI64Load16UName)
   932  		if err != nil {
   933  			return err
   934  		}
   935  		c.emit(NewOperationLoad16(SignedUint64, imm))
   936  	case wasm.OpcodeI64Load32S:
   937  		imm, err := c.readMemoryArg(wasm.OpcodeI64Load32SName)
   938  		if err != nil {
   939  			return err
   940  		}
   941  		c.emit(NewOperationLoad32(true, imm))
   942  	case wasm.OpcodeI64Load32U:
   943  		imm, err := c.readMemoryArg(wasm.OpcodeI64Load32UName)
   944  		if err != nil {
   945  			return err
   946  		}
   947  		c.emit(NewOperationLoad32(false, imm))
   948  	case wasm.OpcodeI32Store:
   949  		imm, err := c.readMemoryArg(wasm.OpcodeI32StoreName)
   950  		if err != nil {
   951  			return err
   952  		}
   953  		c.emit(
   954  			NewOperationStore(UnsignedTypeI32, imm),
   955  		)
   956  	case wasm.OpcodeI64Store:
   957  		imm, err := c.readMemoryArg(wasm.OpcodeI64StoreName)
   958  		if err != nil {
   959  			return err
   960  		}
   961  		c.emit(
   962  			NewOperationStore(UnsignedTypeI64, imm),
   963  		)
   964  	case wasm.OpcodeF32Store:
   965  		imm, err := c.readMemoryArg(wasm.OpcodeF32StoreName)
   966  		if err != nil {
   967  			return err
   968  		}
   969  		c.emit(
   970  			NewOperationStore(UnsignedTypeF32, imm),
   971  		)
   972  	case wasm.OpcodeF64Store:
   973  		imm, err := c.readMemoryArg(wasm.OpcodeF64StoreName)
   974  		if err != nil {
   975  			return err
   976  		}
   977  		c.emit(
   978  			NewOperationStore(UnsignedTypeF64, imm),
   979  		)
   980  	case wasm.OpcodeI32Store8:
   981  		imm, err := c.readMemoryArg(wasm.OpcodeI32Store8Name)
   982  		if err != nil {
   983  			return err
   984  		}
   985  		c.emit(
   986  			NewOperationStore8(imm),
   987  		)
   988  	case wasm.OpcodeI32Store16:
   989  		imm, err := c.readMemoryArg(wasm.OpcodeI32Store16Name)
   990  		if err != nil {
   991  			return err
   992  		}
   993  		c.emit(
   994  			NewOperationStore16(imm),
   995  		)
   996  	case wasm.OpcodeI64Store8:
   997  		imm, err := c.readMemoryArg(wasm.OpcodeI64Store8Name)
   998  		if err != nil {
   999  			return err
  1000  		}
  1001  		c.emit(
  1002  			NewOperationStore8(imm),
  1003  		)
  1004  	case wasm.OpcodeI64Store16:
  1005  		imm, err := c.readMemoryArg(wasm.OpcodeI64Store16Name)
  1006  		if err != nil {
  1007  			return err
  1008  		}
  1009  		c.emit(
  1010  			NewOperationStore16(imm),
  1011  		)
  1012  	case wasm.OpcodeI64Store32:
  1013  		imm, err := c.readMemoryArg(wasm.OpcodeI64Store32Name)
  1014  		if err != nil {
  1015  			return err
  1016  		}
  1017  		c.emit(
  1018  			NewOperationStore32(imm),
  1019  		)
  1020  	case wasm.OpcodeMemorySize:
  1021  		c.result.UsesMemory = true
  1022  		c.pc++ // Skip the reserved one byte.
  1023  		c.emit(
  1024  			NewOperationMemorySize(),
  1025  		)
  1026  	case wasm.OpcodeMemoryGrow:
  1027  		c.result.UsesMemory = true
  1028  		c.pc++ // Skip the reserved one byte.
  1029  		c.emit(
  1030  			NewOperationMemoryGrow(),
  1031  		)
  1032  	case wasm.OpcodeI32Const:
  1033  		val, num, err := leb128.LoadInt32(c.body[c.pc+1:])
  1034  		if err != nil {
  1035  			return fmt.Errorf("reading i32.const value: %v", err)
  1036  		}
  1037  		c.pc += num
  1038  		c.emit(
  1039  			NewOperationConstI32(uint32(val)),
  1040  		)
  1041  	case wasm.OpcodeI64Const:
  1042  		val, num, err := leb128.LoadInt64(c.body[c.pc+1:])
  1043  		if err != nil {
  1044  			return fmt.Errorf("reading i64.const value: %v", err)
  1045  		}
  1046  		c.pc += num
  1047  		c.emit(
  1048  			NewOperationConstI64(uint64(val)),
  1049  		)
  1050  	case wasm.OpcodeF32Const:
  1051  		v := math.Float32frombits(binary.LittleEndian.Uint32(c.body[c.pc+1:]))
  1052  		c.pc += 4
  1053  		c.emit(
  1054  			NewOperationConstF32(v),
  1055  		)
  1056  	case wasm.OpcodeF64Const:
  1057  		v := math.Float64frombits(binary.LittleEndian.Uint64(c.body[c.pc+1:]))
  1058  		c.pc += 8
  1059  		c.emit(
  1060  			NewOperationConstF64(v),
  1061  		)
  1062  	case wasm.OpcodeI32Eqz:
  1063  		c.emit(
  1064  			NewOperationEqz(UnsignedInt32),
  1065  		)
  1066  	case wasm.OpcodeI32Eq:
  1067  		c.emit(
  1068  			NewOperationEq(UnsignedTypeI32),
  1069  		)
  1070  	case wasm.OpcodeI32Ne:
  1071  		c.emit(
  1072  			NewOperationNe(UnsignedTypeI32),
  1073  		)
  1074  	case wasm.OpcodeI32LtS:
  1075  		c.emit(
  1076  			NewOperationLt(SignedTypeInt32),
  1077  		)
  1078  	case wasm.OpcodeI32LtU:
  1079  		c.emit(
  1080  			NewOperationLt(SignedTypeUint32),
  1081  		)
  1082  	case wasm.OpcodeI32GtS:
  1083  		c.emit(
  1084  			NewOperationGt(SignedTypeInt32),
  1085  		)
  1086  	case wasm.OpcodeI32GtU:
  1087  		c.emit(
  1088  			NewOperationGt(SignedTypeUint32),
  1089  		)
  1090  	case wasm.OpcodeI32LeS:
  1091  		c.emit(
  1092  			NewOperationLe(SignedTypeInt32),
  1093  		)
  1094  	case wasm.OpcodeI32LeU:
  1095  		c.emit(
  1096  			NewOperationLe(SignedTypeUint32),
  1097  		)
  1098  	case wasm.OpcodeI32GeS:
  1099  		c.emit(
  1100  			NewOperationGe(SignedTypeInt32),
  1101  		)
  1102  	case wasm.OpcodeI32GeU:
  1103  		c.emit(
  1104  			NewOperationGe(SignedTypeUint32),
  1105  		)
  1106  	case wasm.OpcodeI64Eqz:
  1107  		c.emit(
  1108  			NewOperationEqz(UnsignedInt64),
  1109  		)
  1110  	case wasm.OpcodeI64Eq:
  1111  		c.emit(
  1112  			NewOperationEq(UnsignedTypeI64),
  1113  		)
  1114  	case wasm.OpcodeI64Ne:
  1115  		c.emit(
  1116  			NewOperationNe(UnsignedTypeI64),
  1117  		)
  1118  	case wasm.OpcodeI64LtS:
  1119  		c.emit(
  1120  			NewOperationLt(SignedTypeInt64),
  1121  		)
  1122  	case wasm.OpcodeI64LtU:
  1123  		c.emit(
  1124  			NewOperationLt(SignedTypeUint64),
  1125  		)
  1126  	case wasm.OpcodeI64GtS:
  1127  		c.emit(
  1128  			NewOperationGt(SignedTypeInt64),
  1129  		)
  1130  	case wasm.OpcodeI64GtU:
  1131  		c.emit(
  1132  			NewOperationGt(SignedTypeUint64),
  1133  		)
  1134  	case wasm.OpcodeI64LeS:
  1135  		c.emit(
  1136  			NewOperationLe(SignedTypeInt64),
  1137  		)
  1138  	case wasm.OpcodeI64LeU:
  1139  		c.emit(
  1140  			NewOperationLe(SignedTypeUint64),
  1141  		)
  1142  	case wasm.OpcodeI64GeS:
  1143  		c.emit(
  1144  			NewOperationGe(SignedTypeInt64),
  1145  		)
  1146  	case wasm.OpcodeI64GeU:
  1147  		c.emit(
  1148  			NewOperationGe(SignedTypeUint64),
  1149  		)
  1150  	case wasm.OpcodeF32Eq:
  1151  		c.emit(
  1152  			NewOperationEq(UnsignedTypeF32),
  1153  		)
  1154  	case wasm.OpcodeF32Ne:
  1155  		c.emit(
  1156  			NewOperationNe(UnsignedTypeF32),
  1157  		)
  1158  	case wasm.OpcodeF32Lt:
  1159  		c.emit(
  1160  			NewOperationLt(SignedTypeFloat32),
  1161  		)
  1162  	case wasm.OpcodeF32Gt:
  1163  		c.emit(
  1164  			NewOperationGt(SignedTypeFloat32),
  1165  		)
  1166  	case wasm.OpcodeF32Le:
  1167  		c.emit(
  1168  			NewOperationLe(SignedTypeFloat32),
  1169  		)
  1170  	case wasm.OpcodeF32Ge:
  1171  		c.emit(
  1172  			NewOperationGe(SignedTypeFloat32),
  1173  		)
  1174  	case wasm.OpcodeF64Eq:
  1175  		c.emit(
  1176  			NewOperationEq(UnsignedTypeF64),
  1177  		)
  1178  	case wasm.OpcodeF64Ne:
  1179  		c.emit(
  1180  			NewOperationNe(UnsignedTypeF64),
  1181  		)
  1182  	case wasm.OpcodeF64Lt:
  1183  		c.emit(
  1184  			NewOperationLt(SignedTypeFloat64),
  1185  		)
  1186  	case wasm.OpcodeF64Gt:
  1187  		c.emit(
  1188  			NewOperationGt(SignedTypeFloat64),
  1189  		)
  1190  	case wasm.OpcodeF64Le:
  1191  		c.emit(
  1192  			NewOperationLe(SignedTypeFloat64),
  1193  		)
  1194  	case wasm.OpcodeF64Ge:
  1195  		c.emit(
  1196  			NewOperationGe(SignedTypeFloat64),
  1197  		)
  1198  	case wasm.OpcodeI32Clz:
  1199  		c.emit(
  1200  			NewOperationClz(UnsignedInt32),
  1201  		)
  1202  	case wasm.OpcodeI32Ctz:
  1203  		c.emit(
  1204  			NewOperationCtz(UnsignedInt32),
  1205  		)
  1206  	case wasm.OpcodeI32Popcnt:
  1207  		c.emit(
  1208  			NewOperationPopcnt(UnsignedInt32),
  1209  		)
  1210  	case wasm.OpcodeI32Add:
  1211  		c.emit(
  1212  			NewOperationAdd(UnsignedTypeI32),
  1213  		)
  1214  	case wasm.OpcodeI32Sub:
  1215  		c.emit(
  1216  			NewOperationSub(UnsignedTypeI32),
  1217  		)
  1218  	case wasm.OpcodeI32Mul:
  1219  		c.emit(
  1220  			NewOperationMul(UnsignedTypeI32),
  1221  		)
  1222  	case wasm.OpcodeI32DivS:
  1223  		c.emit(
  1224  			NewOperationDiv(SignedTypeInt32),
  1225  		)
  1226  	case wasm.OpcodeI32DivU:
  1227  		c.emit(
  1228  			NewOperationDiv(SignedTypeUint32),
  1229  		)
  1230  	case wasm.OpcodeI32RemS:
  1231  		c.emit(
  1232  			NewOperationRem(SignedInt32),
  1233  		)
  1234  	case wasm.OpcodeI32RemU:
  1235  		c.emit(
  1236  			NewOperationRem(SignedUint32),
  1237  		)
  1238  	case wasm.OpcodeI32And:
  1239  		c.emit(
  1240  			NewOperationAnd(UnsignedInt32),
  1241  		)
  1242  	case wasm.OpcodeI32Or:
  1243  		c.emit(
  1244  			NewOperationOr(UnsignedInt32),
  1245  		)
  1246  	case wasm.OpcodeI32Xor:
  1247  		c.emit(
  1248  			NewOperationXor(UnsignedInt64),
  1249  		)
  1250  	case wasm.OpcodeI32Shl:
  1251  		c.emit(
  1252  			NewOperationShl(UnsignedInt32),
  1253  		)
  1254  	case wasm.OpcodeI32ShrS:
  1255  		c.emit(
  1256  			NewOperationShr(SignedInt32),
  1257  		)
  1258  	case wasm.OpcodeI32ShrU:
  1259  		c.emit(
  1260  			NewOperationShr(SignedUint32),
  1261  		)
  1262  	case wasm.OpcodeI32Rotl:
  1263  		c.emit(
  1264  			NewOperationRotl(UnsignedInt32),
  1265  		)
  1266  	case wasm.OpcodeI32Rotr:
  1267  		c.emit(
  1268  			NewOperationRotr(UnsignedInt32),
  1269  		)
  1270  	case wasm.OpcodeI64Clz:
  1271  		c.emit(
  1272  			NewOperationClz(UnsignedInt64),
  1273  		)
  1274  	case wasm.OpcodeI64Ctz:
  1275  		c.emit(
  1276  			NewOperationCtz(UnsignedInt64),
  1277  		)
  1278  	case wasm.OpcodeI64Popcnt:
  1279  		c.emit(
  1280  			NewOperationPopcnt(UnsignedInt64),
  1281  		)
  1282  	case wasm.OpcodeI64Add:
  1283  		c.emit(
  1284  			NewOperationAdd(UnsignedTypeI64),
  1285  		)
  1286  	case wasm.OpcodeI64Sub:
  1287  		c.emit(
  1288  			NewOperationSub(UnsignedTypeI64),
  1289  		)
  1290  	case wasm.OpcodeI64Mul:
  1291  		c.emit(
  1292  			NewOperationMul(UnsignedTypeI64),
  1293  		)
  1294  	case wasm.OpcodeI64DivS:
  1295  		c.emit(
  1296  			NewOperationDiv(SignedTypeInt64),
  1297  		)
  1298  	case wasm.OpcodeI64DivU:
  1299  		c.emit(
  1300  			NewOperationDiv(SignedTypeUint64),
  1301  		)
  1302  	case wasm.OpcodeI64RemS:
  1303  		c.emit(
  1304  			NewOperationRem(SignedInt64),
  1305  		)
  1306  	case wasm.OpcodeI64RemU:
  1307  		c.emit(
  1308  			NewOperationRem(SignedUint64),
  1309  		)
  1310  	case wasm.OpcodeI64And:
  1311  		c.emit(
  1312  			NewOperationAnd(UnsignedInt64),
  1313  		)
  1314  	case wasm.OpcodeI64Or:
  1315  		c.emit(
  1316  			NewOperationOr(UnsignedInt64),
  1317  		)
  1318  	case wasm.OpcodeI64Xor:
  1319  		c.emit(
  1320  			NewOperationXor(UnsignedInt64),
  1321  		)
  1322  	case wasm.OpcodeI64Shl:
  1323  		c.emit(
  1324  			NewOperationShl(UnsignedInt64),
  1325  		)
  1326  	case wasm.OpcodeI64ShrS:
  1327  		c.emit(
  1328  			NewOperationShr(SignedInt64),
  1329  		)
  1330  	case wasm.OpcodeI64ShrU:
  1331  		c.emit(
  1332  			NewOperationShr(SignedUint64),
  1333  		)
  1334  	case wasm.OpcodeI64Rotl:
  1335  		c.emit(
  1336  			NewOperationRotl(UnsignedInt64),
  1337  		)
  1338  	case wasm.OpcodeI64Rotr:
  1339  		c.emit(
  1340  			NewOperationRotr(UnsignedInt64),
  1341  		)
  1342  	case wasm.OpcodeF32Abs:
  1343  		c.emit(
  1344  			NewOperationAbs(Float32),
  1345  		)
  1346  	case wasm.OpcodeF32Neg:
  1347  		c.emit(
  1348  			NewOperationNeg(Float32),
  1349  		)
  1350  	case wasm.OpcodeF32Ceil:
  1351  		c.emit(
  1352  			NewOperationCeil(Float32),
  1353  		)
  1354  	case wasm.OpcodeF32Floor:
  1355  		c.emit(
  1356  			NewOperationFloor(Float32),
  1357  		)
  1358  	case wasm.OpcodeF32Trunc:
  1359  		c.emit(
  1360  			NewOperationTrunc(Float32),
  1361  		)
  1362  	case wasm.OpcodeF32Nearest:
  1363  		c.emit(
  1364  			NewOperationNearest(Float32),
  1365  		)
  1366  	case wasm.OpcodeF32Sqrt:
  1367  		c.emit(
  1368  			NewOperationSqrt(Float32),
  1369  		)
  1370  	case wasm.OpcodeF32Add:
  1371  		c.emit(
  1372  			NewOperationAdd(UnsignedTypeF32),
  1373  		)
  1374  	case wasm.OpcodeF32Sub:
  1375  		c.emit(
  1376  			NewOperationSub(UnsignedTypeF32),
  1377  		)
  1378  	case wasm.OpcodeF32Mul:
  1379  		c.emit(
  1380  			NewOperationMul(UnsignedTypeF32),
  1381  		)
  1382  	case wasm.OpcodeF32Div:
  1383  		c.emit(
  1384  			NewOperationDiv(SignedTypeFloat32),
  1385  		)
  1386  	case wasm.OpcodeF32Min:
  1387  		c.emit(
  1388  			NewOperationMin(Float32),
  1389  		)
  1390  	case wasm.OpcodeF32Max:
  1391  		c.emit(
  1392  			NewOperationMax(Float32),
  1393  		)
  1394  	case wasm.OpcodeF32Copysign:
  1395  		c.emit(
  1396  			NewOperationCopysign(Float32),
  1397  		)
  1398  	case wasm.OpcodeF64Abs:
  1399  		c.emit(
  1400  			NewOperationAbs(Float64),
  1401  		)
  1402  	case wasm.OpcodeF64Neg:
  1403  		c.emit(
  1404  			NewOperationNeg(Float64),
  1405  		)
  1406  	case wasm.OpcodeF64Ceil:
  1407  		c.emit(
  1408  			NewOperationCeil(Float64),
  1409  		)
  1410  	case wasm.OpcodeF64Floor:
  1411  		c.emit(
  1412  			NewOperationFloor(Float64),
  1413  		)
  1414  	case wasm.OpcodeF64Trunc:
  1415  		c.emit(
  1416  			NewOperationTrunc(Float64),
  1417  		)
  1418  	case wasm.OpcodeF64Nearest:
  1419  		c.emit(
  1420  			NewOperationNearest(Float64),
  1421  		)
  1422  	case wasm.OpcodeF64Sqrt:
  1423  		c.emit(
  1424  			NewOperationSqrt(Float64),
  1425  		)
  1426  	case wasm.OpcodeF64Add:
  1427  		c.emit(
  1428  			NewOperationAdd(UnsignedTypeF64),
  1429  		)
  1430  	case wasm.OpcodeF64Sub:
  1431  		c.emit(
  1432  			NewOperationSub(UnsignedTypeF64),
  1433  		)
  1434  	case wasm.OpcodeF64Mul:
  1435  		c.emit(
  1436  			NewOperationMul(UnsignedTypeF64),
  1437  		)
  1438  	case wasm.OpcodeF64Div:
  1439  		c.emit(
  1440  			NewOperationDiv(SignedTypeFloat64),
  1441  		)
  1442  	case wasm.OpcodeF64Min:
  1443  		c.emit(
  1444  			NewOperationMin(Float64),
  1445  		)
  1446  	case wasm.OpcodeF64Max:
  1447  		c.emit(
  1448  			NewOperationMax(Float64),
  1449  		)
  1450  	case wasm.OpcodeF64Copysign:
  1451  		c.emit(
  1452  			NewOperationCopysign(Float64),
  1453  		)
  1454  	case wasm.OpcodeI32WrapI64:
  1455  		c.emit(
  1456  			NewOperationI32WrapFromI64(),
  1457  		)
  1458  	case wasm.OpcodeI32TruncF32S:
  1459  		c.emit(
  1460  			NewOperationITruncFromF(Float32, SignedInt32, false),
  1461  		)
  1462  	case wasm.OpcodeI32TruncF32U:
  1463  		c.emit(
  1464  			NewOperationITruncFromF(Float32, SignedUint32, false),
  1465  		)
  1466  	case wasm.OpcodeI32TruncF64S:
  1467  		c.emit(
  1468  			NewOperationITruncFromF(Float64, SignedInt32, false),
  1469  		)
  1470  	case wasm.OpcodeI32TruncF64U:
  1471  		c.emit(
  1472  			NewOperationITruncFromF(Float64, SignedUint32, false),
  1473  		)
  1474  	case wasm.OpcodeI64ExtendI32S:
  1475  		c.emit(
  1476  			NewOperationExtend(true),
  1477  		)
  1478  	case wasm.OpcodeI64ExtendI32U:
  1479  		c.emit(
  1480  			NewOperationExtend(false),
  1481  		)
  1482  	case wasm.OpcodeI64TruncF32S:
  1483  		c.emit(
  1484  			NewOperationITruncFromF(Float32, SignedInt64, false),
  1485  		)
  1486  	case wasm.OpcodeI64TruncF32U:
  1487  		c.emit(
  1488  			NewOperationITruncFromF(Float32, SignedUint64, false),
  1489  		)
  1490  	case wasm.OpcodeI64TruncF64S:
  1491  		c.emit(
  1492  			NewOperationITruncFromF(Float64, SignedInt64, false),
  1493  		)
  1494  	case wasm.OpcodeI64TruncF64U:
  1495  		c.emit(
  1496  			NewOperationITruncFromF(Float64, SignedUint64, false),
  1497  		)
  1498  	case wasm.OpcodeF32ConvertI32S:
  1499  		c.emit(
  1500  			NewOperationFConvertFromI(SignedInt32, Float32),
  1501  		)
  1502  	case wasm.OpcodeF32ConvertI32U:
  1503  		c.emit(
  1504  			NewOperationFConvertFromI(SignedUint32, Float32),
  1505  		)
  1506  	case wasm.OpcodeF32ConvertI64S:
  1507  		c.emit(
  1508  			NewOperationFConvertFromI(SignedInt64, Float32),
  1509  		)
  1510  	case wasm.OpcodeF32ConvertI64U:
  1511  		c.emit(
  1512  			NewOperationFConvertFromI(SignedUint64, Float32),
  1513  		)
  1514  	case wasm.OpcodeF32DemoteF64:
  1515  		c.emit(
  1516  			NewOperationF32DemoteFromF64(),
  1517  		)
  1518  	case wasm.OpcodeF64ConvertI32S:
  1519  		c.emit(
  1520  			NewOperationFConvertFromI(SignedInt32, Float64),
  1521  		)
  1522  	case wasm.OpcodeF64ConvertI32U:
  1523  		c.emit(
  1524  			NewOperationFConvertFromI(SignedUint32, Float64),
  1525  		)
  1526  	case wasm.OpcodeF64ConvertI64S:
  1527  		c.emit(
  1528  			NewOperationFConvertFromI(SignedInt64, Float64),
  1529  		)
  1530  	case wasm.OpcodeF64ConvertI64U:
  1531  		c.emit(
  1532  			NewOperationFConvertFromI(SignedUint64, Float64),
  1533  		)
  1534  	case wasm.OpcodeF64PromoteF32:
  1535  		c.emit(
  1536  			NewOperationF64PromoteFromF32(),
  1537  		)
  1538  	case wasm.OpcodeI32ReinterpretF32:
  1539  		c.emit(
  1540  			NewOperationI32ReinterpretFromF32(),
  1541  		)
  1542  	case wasm.OpcodeI64ReinterpretF64:
  1543  		c.emit(
  1544  			NewOperationI64ReinterpretFromF64(),
  1545  		)
  1546  	case wasm.OpcodeF32ReinterpretI32:
  1547  		c.emit(
  1548  			NewOperationF32ReinterpretFromI32(),
  1549  		)
  1550  	case wasm.OpcodeF64ReinterpretI64:
  1551  		c.emit(
  1552  			NewOperationF64ReinterpretFromI64(),
  1553  		)
  1554  	case wasm.OpcodeI32Extend8S:
  1555  		c.emit(
  1556  			NewOperationSignExtend32From8(),
  1557  		)
  1558  	case wasm.OpcodeI32Extend16S:
  1559  		c.emit(
  1560  			NewOperationSignExtend32From16(),
  1561  		)
  1562  	case wasm.OpcodeI64Extend8S:
  1563  		c.emit(
  1564  			NewOperationSignExtend64From8(),
  1565  		)
  1566  	case wasm.OpcodeI64Extend16S:
  1567  		c.emit(
  1568  			NewOperationSignExtend64From16(),
  1569  		)
  1570  	case wasm.OpcodeI64Extend32S:
  1571  		c.emit(
  1572  			NewOperationSignExtend64From32(),
  1573  		)
  1574  	case wasm.OpcodeRefFunc:
  1575  		c.pc++
  1576  		index, num, err := leb128.LoadUint32(c.body[c.pc:])
  1577  		if err != nil {
  1578  			return fmt.Errorf("failed to read function index for ref.func: %v", err)
  1579  		}
  1580  		c.pc += num - 1
  1581  		c.emit(
  1582  			NewOperationRefFunc(index),
  1583  		)
  1584  	case wasm.OpcodeRefNull:
  1585  		c.pc++ // Skip the type of reftype as every ref value is opaque pointer.
  1586  		c.emit(
  1587  			NewOperationConstI64(0),
  1588  		)
  1589  	case wasm.OpcodeRefIsNull:
  1590  		// Simply compare the opaque pointer (i64) with zero.
  1591  		c.emit(
  1592  			NewOperationEqz(UnsignedInt64),
  1593  		)
  1594  	case wasm.OpcodeTableGet:
  1595  		c.pc++
  1596  		tableIndex, num, err := leb128.LoadUint32(c.body[c.pc:])
  1597  		if err != nil {
  1598  			return fmt.Errorf("failed to read function index for table.get: %v", err)
  1599  		}
  1600  		c.pc += num - 1
  1601  		c.emit(
  1602  			NewOperationTableGet(tableIndex),
  1603  		)
  1604  	case wasm.OpcodeTableSet:
  1605  		c.pc++
  1606  		tableIndex, num, err := leb128.LoadUint32(c.body[c.pc:])
  1607  		if err != nil {
  1608  			return fmt.Errorf("failed to read function index for table.set: %v", err)
  1609  		}
  1610  		c.pc += num - 1
  1611  		c.emit(
  1612  			NewOperationTableSet(tableIndex),
  1613  		)
  1614  	case wasm.OpcodeMiscPrefix:
  1615  		c.pc++
  1616  		// A misc opcode is encoded as an unsigned variable 32-bit integer.
  1617  		miscOp, num, err := leb128.LoadUint32(c.body[c.pc:])
  1618  		if err != nil {
  1619  			return fmt.Errorf("failed to read misc opcode: %v", err)
  1620  		}
  1621  		c.pc += num - 1
  1622  		switch byte(miscOp) {
  1623  		case wasm.OpcodeMiscI32TruncSatF32S:
  1624  			c.emit(
  1625  				NewOperationITruncFromF(Float32, SignedInt32, true),
  1626  			)
  1627  		case wasm.OpcodeMiscI32TruncSatF32U:
  1628  			c.emit(
  1629  				NewOperationITruncFromF(Float32, SignedUint32, true),
  1630  			)
  1631  		case wasm.OpcodeMiscI32TruncSatF64S:
  1632  			c.emit(
  1633  				NewOperationITruncFromF(Float64, SignedInt32, true),
  1634  			)
  1635  		case wasm.OpcodeMiscI32TruncSatF64U:
  1636  			c.emit(
  1637  				NewOperationITruncFromF(Float64, SignedUint32, true),
  1638  			)
  1639  		case wasm.OpcodeMiscI64TruncSatF32S:
  1640  			c.emit(
  1641  				NewOperationITruncFromF(Float32, SignedInt64, true),
  1642  			)
  1643  		case wasm.OpcodeMiscI64TruncSatF32U:
  1644  			c.emit(
  1645  				NewOperationITruncFromF(Float32, SignedUint64, true),
  1646  			)
  1647  		case wasm.OpcodeMiscI64TruncSatF64S:
  1648  			c.emit(
  1649  				NewOperationITruncFromF(Float64, SignedInt64, true),
  1650  			)
  1651  		case wasm.OpcodeMiscI64TruncSatF64U:
  1652  			c.emit(
  1653  				NewOperationITruncFromF(Float64, SignedUint64, true),
  1654  			)
  1655  		case wasm.OpcodeMiscMemoryInit:
  1656  			c.result.UsesMemory = true
  1657  			dataIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  1658  			if err != nil {
  1659  				return fmt.Errorf("reading i32.const value: %v", err)
  1660  			}
  1661  			c.pc += num + 1 // +1 to skip the memory index which is fixed to zero.
  1662  			c.emit(
  1663  				NewOperationMemoryInit(dataIndex),
  1664  			)
  1665  		case wasm.OpcodeMiscDataDrop:
  1666  			dataIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  1667  			if err != nil {
  1668  				return fmt.Errorf("reading i32.const value: %v", err)
  1669  			}
  1670  			c.pc += num
  1671  			c.emit(
  1672  				NewOperationDataDrop(dataIndex),
  1673  			)
  1674  		case wasm.OpcodeMiscMemoryCopy:
  1675  			c.result.UsesMemory = true
  1676  			c.pc += 2 // +2 to skip two memory indexes which are fixed to zero.
  1677  			c.emit(
  1678  				NewOperationMemoryCopy(),
  1679  			)
  1680  		case wasm.OpcodeMiscMemoryFill:
  1681  			c.result.UsesMemory = true
  1682  			c.pc += 1 // +1 to skip the memory index which is fixed to zero.
  1683  			c.emit(
  1684  				NewOperationMemoryFill(),
  1685  			)
  1686  		case wasm.OpcodeMiscTableInit:
  1687  			elemIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  1688  			if err != nil {
  1689  				return fmt.Errorf("reading i32.const value: %v", err)
  1690  			}
  1691  			c.pc += num
  1692  			// Read table index which is fixed to zero currently.
  1693  			tableIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  1694  			if err != nil {
  1695  				return fmt.Errorf("reading i32.const value: %v", err)
  1696  			}
  1697  			c.pc += num
  1698  			c.emit(
  1699  				NewOperationTableInit(elemIndex, tableIndex),
  1700  			)
  1701  		case wasm.OpcodeMiscElemDrop:
  1702  			elemIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  1703  			if err != nil {
  1704  				return fmt.Errorf("reading i32.const value: %v", err)
  1705  			}
  1706  			c.pc += num
  1707  			c.emit(
  1708  				NewOperationElemDrop(elemIndex),
  1709  			)
  1710  		case wasm.OpcodeMiscTableCopy:
  1711  			// Read the source table inde.g.
  1712  			dst, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  1713  			if err != nil {
  1714  				return fmt.Errorf("reading i32.const value: %v", err)
  1715  			}
  1716  			c.pc += num
  1717  			// Read the destination table inde.g.
  1718  			src, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  1719  			if err != nil {
  1720  				return fmt.Errorf("reading i32.const value: %v", err)
  1721  			}
  1722  			c.pc += num
  1723  			c.emit(
  1724  				NewOperationTableCopy(src, dst),
  1725  			)
  1726  		case wasm.OpcodeMiscTableGrow:
  1727  			// Read the source table inde.g.
  1728  			tableIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  1729  			if err != nil {
  1730  				return fmt.Errorf("reading i32.const value: %v", err)
  1731  			}
  1732  			c.pc += num
  1733  			c.emit(
  1734  				NewOperationTableGrow(tableIndex),
  1735  			)
  1736  		case wasm.OpcodeMiscTableSize:
  1737  			// Read the source table inde.g.
  1738  			tableIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  1739  			if err != nil {
  1740  				return fmt.Errorf("reading i32.const value: %v", err)
  1741  			}
  1742  			c.pc += num
  1743  			c.emit(
  1744  				NewOperationTableSize(tableIndex),
  1745  			)
  1746  		case wasm.OpcodeMiscTableFill:
  1747  			// Read the source table index.
  1748  			tableIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  1749  			if err != nil {
  1750  				return fmt.Errorf("reading i32.const value: %v", err)
  1751  			}
  1752  			c.pc += num
  1753  			c.emit(
  1754  				NewOperationTableFill(tableIndex),
  1755  			)
  1756  		default:
  1757  			return fmt.Errorf("unsupported misc instruction in wazeroir: 0x%x", op)
  1758  		}
  1759  	case wasm.OpcodeVecPrefix:
  1760  		c.pc++
  1761  		switch vecOp := c.body[c.pc]; vecOp {
  1762  		case wasm.OpcodeVecV128Const:
  1763  			c.pc++
  1764  			lo := binary.LittleEndian.Uint64(c.body[c.pc : c.pc+8])
  1765  			c.pc += 8
  1766  			hi := binary.LittleEndian.Uint64(c.body[c.pc : c.pc+8])
  1767  			c.emit(
  1768  				NewOperationV128Const(lo, hi),
  1769  			)
  1770  			c.pc += 7
  1771  		case wasm.OpcodeVecV128Load:
  1772  			arg, err := c.readMemoryArg(wasm.OpcodeI32LoadName)
  1773  			if err != nil {
  1774  				return err
  1775  			}
  1776  			c.emit(
  1777  				NewOperationV128Load(V128LoadType128, arg),
  1778  			)
  1779  		case wasm.OpcodeVecV128Load8x8s:
  1780  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load8x8SName)
  1781  			if err != nil {
  1782  				return err
  1783  			}
  1784  			c.emit(
  1785  				NewOperationV128Load(V128LoadType8x8s, arg),
  1786  			)
  1787  		case wasm.OpcodeVecV128Load8x8u:
  1788  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load8x8UName)
  1789  			if err != nil {
  1790  				return err
  1791  			}
  1792  			c.emit(
  1793  				NewOperationV128Load(V128LoadType8x8u, arg),
  1794  			)
  1795  		case wasm.OpcodeVecV128Load16x4s:
  1796  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load16x4SName)
  1797  			if err != nil {
  1798  				return err
  1799  			}
  1800  			c.emit(
  1801  				NewOperationV128Load(V128LoadType16x4s, arg),
  1802  			)
  1803  		case wasm.OpcodeVecV128Load16x4u:
  1804  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load16x4UName)
  1805  			if err != nil {
  1806  				return err
  1807  			}
  1808  			c.emit(
  1809  				NewOperationV128Load(V128LoadType16x4u, arg),
  1810  			)
  1811  		case wasm.OpcodeVecV128Load32x2s:
  1812  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32x2SName)
  1813  			if err != nil {
  1814  				return err
  1815  			}
  1816  			c.emit(
  1817  				NewOperationV128Load(V128LoadType32x2s, arg),
  1818  			)
  1819  		case wasm.OpcodeVecV128Load32x2u:
  1820  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32x2UName)
  1821  			if err != nil {
  1822  				return err
  1823  			}
  1824  			c.emit(
  1825  				NewOperationV128Load(V128LoadType32x2u, arg),
  1826  			)
  1827  		case wasm.OpcodeVecV128Load8Splat:
  1828  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load8SplatName)
  1829  			if err != nil {
  1830  				return err
  1831  			}
  1832  			c.emit(
  1833  				NewOperationV128Load(V128LoadType8Splat, arg),
  1834  			)
  1835  		case wasm.OpcodeVecV128Load16Splat:
  1836  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load16SplatName)
  1837  			if err != nil {
  1838  				return err
  1839  			}
  1840  			c.emit(
  1841  				NewOperationV128Load(V128LoadType16Splat, arg),
  1842  			)
  1843  		case wasm.OpcodeVecV128Load32Splat:
  1844  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32SplatName)
  1845  			if err != nil {
  1846  				return err
  1847  			}
  1848  			c.emit(
  1849  				NewOperationV128Load(V128LoadType32Splat, arg),
  1850  			)
  1851  		case wasm.OpcodeVecV128Load64Splat:
  1852  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load64SplatName)
  1853  			if err != nil {
  1854  				return err
  1855  			}
  1856  			c.emit(
  1857  				NewOperationV128Load(V128LoadType64Splat, arg),
  1858  			)
  1859  		case wasm.OpcodeVecV128Load32zero:
  1860  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32zeroName)
  1861  			if err != nil {
  1862  				return err
  1863  			}
  1864  			c.emit(
  1865  				NewOperationV128Load(V128LoadType32zero, arg),
  1866  			)
  1867  		case wasm.OpcodeVecV128Load64zero:
  1868  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load64zeroName)
  1869  			if err != nil {
  1870  				return err
  1871  			}
  1872  			c.emit(
  1873  				NewOperationV128Load(V128LoadType64zero, arg),
  1874  			)
  1875  		case wasm.OpcodeVecV128Load8Lane:
  1876  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load8LaneName)
  1877  			if err != nil {
  1878  				return err
  1879  			}
  1880  			c.pc++
  1881  			laneIndex := c.body[c.pc]
  1882  			c.emit(
  1883  				NewOperationV128LoadLane(laneIndex, 8, arg),
  1884  			)
  1885  		case wasm.OpcodeVecV128Load16Lane:
  1886  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load16LaneName)
  1887  			if err != nil {
  1888  				return err
  1889  			}
  1890  			c.pc++
  1891  			laneIndex := c.body[c.pc]
  1892  			c.emit(
  1893  				NewOperationV128LoadLane(laneIndex, 16, arg),
  1894  			)
  1895  		case wasm.OpcodeVecV128Load32Lane:
  1896  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32LaneName)
  1897  			if err != nil {
  1898  				return err
  1899  			}
  1900  			c.pc++
  1901  			laneIndex := c.body[c.pc]
  1902  			c.emit(
  1903  				NewOperationV128LoadLane(laneIndex, 32, arg),
  1904  			)
  1905  		case wasm.OpcodeVecV128Load64Lane:
  1906  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load64LaneName)
  1907  			if err != nil {
  1908  				return err
  1909  			}
  1910  			c.pc++
  1911  			laneIndex := c.body[c.pc]
  1912  			c.emit(
  1913  				NewOperationV128LoadLane(laneIndex, 64, arg),
  1914  			)
  1915  		case wasm.OpcodeVecV128Store:
  1916  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128StoreName)
  1917  			if err != nil {
  1918  				return err
  1919  			}
  1920  			c.emit(
  1921  				NewOperationV128Store(arg),
  1922  			)
  1923  		case wasm.OpcodeVecV128Store8Lane:
  1924  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Store8LaneName)
  1925  			if err != nil {
  1926  				return err
  1927  			}
  1928  			c.pc++
  1929  			laneIndex := c.body[c.pc]
  1930  			c.emit(
  1931  				NewOperationV128StoreLane(laneIndex, 8, arg),
  1932  			)
  1933  		case wasm.OpcodeVecV128Store16Lane:
  1934  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Store16LaneName)
  1935  			if err != nil {
  1936  				return err
  1937  			}
  1938  			c.pc++
  1939  			laneIndex := c.body[c.pc]
  1940  			c.emit(
  1941  				NewOperationV128StoreLane(laneIndex, 16, arg),
  1942  			)
  1943  		case wasm.OpcodeVecV128Store32Lane:
  1944  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Store32LaneName)
  1945  			if err != nil {
  1946  				return err
  1947  			}
  1948  			c.pc++
  1949  			laneIndex := c.body[c.pc]
  1950  			c.emit(
  1951  				NewOperationV128StoreLane(laneIndex, 32, arg),
  1952  			)
  1953  		case wasm.OpcodeVecV128Store64Lane:
  1954  			arg, err := c.readMemoryArg(wasm.OpcodeVecV128Store64LaneName)
  1955  			if err != nil {
  1956  				return err
  1957  			}
  1958  			c.pc++
  1959  			laneIndex := c.body[c.pc]
  1960  			c.emit(
  1961  				NewOperationV128StoreLane(laneIndex, 64, arg),
  1962  			)
  1963  		case wasm.OpcodeVecI8x16ExtractLaneS:
  1964  			c.pc++
  1965  			laneIndex := c.body[c.pc]
  1966  			c.emit(
  1967  				NewOperationV128ExtractLane(laneIndex, true, ShapeI8x16),
  1968  			)
  1969  		case wasm.OpcodeVecI8x16ExtractLaneU:
  1970  			c.pc++
  1971  			laneIndex := c.body[c.pc]
  1972  			c.emit(
  1973  				NewOperationV128ExtractLane(laneIndex, false, ShapeI8x16),
  1974  			)
  1975  		case wasm.OpcodeVecI16x8ExtractLaneS:
  1976  			c.pc++
  1977  			laneIndex := c.body[c.pc]
  1978  			c.emit(
  1979  				NewOperationV128ExtractLane(laneIndex, true, ShapeI16x8),
  1980  			)
  1981  		case wasm.OpcodeVecI16x8ExtractLaneU:
  1982  			c.pc++
  1983  			laneIndex := c.body[c.pc]
  1984  			c.emit(
  1985  				NewOperationV128ExtractLane(laneIndex, false, ShapeI16x8),
  1986  			)
  1987  		case wasm.OpcodeVecI32x4ExtractLane:
  1988  			c.pc++
  1989  			laneIndex := c.body[c.pc]
  1990  			c.emit(
  1991  				NewOperationV128ExtractLane(laneIndex, false, ShapeI32x4),
  1992  			)
  1993  		case wasm.OpcodeVecI64x2ExtractLane:
  1994  			c.pc++
  1995  			laneIndex := c.body[c.pc]
  1996  			c.emit(
  1997  				NewOperationV128ExtractLane(laneIndex, false, ShapeI64x2),
  1998  			)
  1999  		case wasm.OpcodeVecF32x4ExtractLane:
  2000  			c.pc++
  2001  			laneIndex := c.body[c.pc]
  2002  			c.emit(
  2003  				NewOperationV128ExtractLane(laneIndex, false, ShapeF32x4),
  2004  			)
  2005  		case wasm.OpcodeVecF64x2ExtractLane:
  2006  			c.pc++
  2007  			laneIndex := c.body[c.pc]
  2008  			c.emit(
  2009  				NewOperationV128ExtractLane(laneIndex, false, ShapeF64x2),
  2010  			)
  2011  		case wasm.OpcodeVecI8x16ReplaceLane:
  2012  			c.pc++
  2013  			laneIndex := c.body[c.pc]
  2014  			c.emit(
  2015  				NewOperationV128ReplaceLane(laneIndex, ShapeI8x16),
  2016  			)
  2017  		case wasm.OpcodeVecI16x8ReplaceLane:
  2018  			c.pc++
  2019  			laneIndex := c.body[c.pc]
  2020  			c.emit(
  2021  				NewOperationV128ReplaceLane(laneIndex, ShapeI16x8),
  2022  			)
  2023  		case wasm.OpcodeVecI32x4ReplaceLane:
  2024  			c.pc++
  2025  			laneIndex := c.body[c.pc]
  2026  			c.emit(
  2027  				NewOperationV128ReplaceLane(laneIndex, ShapeI32x4),
  2028  			)
  2029  		case wasm.OpcodeVecI64x2ReplaceLane:
  2030  			c.pc++
  2031  			laneIndex := c.body[c.pc]
  2032  			c.emit(
  2033  				NewOperationV128ReplaceLane(laneIndex, ShapeI64x2),
  2034  			)
  2035  		case wasm.OpcodeVecF32x4ReplaceLane:
  2036  			c.pc++
  2037  			laneIndex := c.body[c.pc]
  2038  			c.emit(
  2039  				NewOperationV128ReplaceLane(laneIndex, ShapeF32x4),
  2040  			)
  2041  		case wasm.OpcodeVecF64x2ReplaceLane:
  2042  			c.pc++
  2043  			laneIndex := c.body[c.pc]
  2044  			c.emit(
  2045  				NewOperationV128ReplaceLane(laneIndex, ShapeF64x2),
  2046  			)
  2047  		case wasm.OpcodeVecI8x16Splat:
  2048  			c.emit(
  2049  				NewOperationV128Splat(ShapeI8x16),
  2050  			)
  2051  		case wasm.OpcodeVecI16x8Splat:
  2052  			c.emit(
  2053  				NewOperationV128Splat(ShapeI16x8),
  2054  			)
  2055  		case wasm.OpcodeVecI32x4Splat:
  2056  			c.emit(
  2057  				NewOperationV128Splat(ShapeI32x4),
  2058  			)
  2059  		case wasm.OpcodeVecI64x2Splat:
  2060  			c.emit(
  2061  				NewOperationV128Splat(ShapeI64x2),
  2062  			)
  2063  		case wasm.OpcodeVecF32x4Splat:
  2064  			c.emit(
  2065  				NewOperationV128Splat(ShapeF32x4),
  2066  			)
  2067  		case wasm.OpcodeVecF64x2Splat:
  2068  			c.emit(
  2069  				NewOperationV128Splat(ShapeF64x2),
  2070  			)
  2071  		case wasm.OpcodeVecI8x16Swizzle:
  2072  			c.emit(
  2073  				NewOperationV128Swizzle(),
  2074  			)
  2075  		case wasm.OpcodeVecV128i8x16Shuffle:
  2076  			c.pc++
  2077  			lanes := make([]uint64, 16)
  2078  			for i := uint64(0); i < 16; i++ {
  2079  				lanes[i] = uint64(c.body[c.pc+i])
  2080  			}
  2081  			op := NewOperationV128Shuffle(lanes)
  2082  			c.emit(op)
  2083  			c.pc += 15
  2084  		case wasm.OpcodeVecV128AnyTrue:
  2085  			c.emit(
  2086  				NewOperationV128AnyTrue(),
  2087  			)
  2088  		case wasm.OpcodeVecI8x16AllTrue:
  2089  			c.emit(
  2090  				NewOperationV128AllTrue(ShapeI8x16),
  2091  			)
  2092  		case wasm.OpcodeVecI16x8AllTrue:
  2093  			c.emit(
  2094  				NewOperationV128AllTrue(ShapeI16x8),
  2095  			)
  2096  		case wasm.OpcodeVecI32x4AllTrue:
  2097  			c.emit(
  2098  				NewOperationV128AllTrue(ShapeI32x4),
  2099  			)
  2100  		case wasm.OpcodeVecI64x2AllTrue:
  2101  			c.emit(
  2102  				NewOperationV128AllTrue(ShapeI64x2),
  2103  			)
  2104  		case wasm.OpcodeVecI8x16BitMask:
  2105  			c.emit(
  2106  				NewOperationV128BitMask(ShapeI8x16),
  2107  			)
  2108  		case wasm.OpcodeVecI16x8BitMask:
  2109  			c.emit(
  2110  				NewOperationV128BitMask(ShapeI16x8),
  2111  			)
  2112  		case wasm.OpcodeVecI32x4BitMask:
  2113  			c.emit(
  2114  				NewOperationV128BitMask(ShapeI32x4),
  2115  			)
  2116  		case wasm.OpcodeVecI64x2BitMask:
  2117  			c.emit(
  2118  				NewOperationV128BitMask(ShapeI64x2),
  2119  			)
  2120  		case wasm.OpcodeVecV128And:
  2121  			c.emit(
  2122  				NewOperationV128And(),
  2123  			)
  2124  		case wasm.OpcodeVecV128Not:
  2125  			c.emit(
  2126  				NewOperationV128Not(),
  2127  			)
  2128  		case wasm.OpcodeVecV128Or:
  2129  			c.emit(
  2130  				NewOperationV128Or(),
  2131  			)
  2132  		case wasm.OpcodeVecV128Xor:
  2133  			c.emit(
  2134  				NewOperationV128Xor(),
  2135  			)
  2136  		case wasm.OpcodeVecV128Bitselect:
  2137  			c.emit(
  2138  				NewOperationV128Bitselect(),
  2139  			)
  2140  		case wasm.OpcodeVecV128AndNot:
  2141  			c.emit(
  2142  				NewOperationV128AndNot(),
  2143  			)
  2144  		case wasm.OpcodeVecI8x16Shl:
  2145  			c.emit(
  2146  				NewOperationV128Shl(ShapeI8x16),
  2147  			)
  2148  		case wasm.OpcodeVecI8x16ShrS:
  2149  			c.emit(
  2150  				NewOperationV128Shr(ShapeI8x16, true),
  2151  			)
  2152  		case wasm.OpcodeVecI8x16ShrU:
  2153  			c.emit(
  2154  				NewOperationV128Shr(ShapeI8x16, false),
  2155  			)
  2156  		case wasm.OpcodeVecI16x8Shl:
  2157  			c.emit(
  2158  				NewOperationV128Shl(ShapeI16x8),
  2159  			)
  2160  		case wasm.OpcodeVecI16x8ShrS:
  2161  			c.emit(
  2162  				NewOperationV128Shr(ShapeI16x8, true),
  2163  			)
  2164  		case wasm.OpcodeVecI16x8ShrU:
  2165  			c.emit(
  2166  				NewOperationV128Shr(ShapeI16x8, false),
  2167  			)
  2168  		case wasm.OpcodeVecI32x4Shl:
  2169  			c.emit(
  2170  				NewOperationV128Shl(ShapeI32x4),
  2171  			)
  2172  		case wasm.OpcodeVecI32x4ShrS:
  2173  			c.emit(
  2174  				NewOperationV128Shr(ShapeI32x4, true),
  2175  			)
  2176  		case wasm.OpcodeVecI32x4ShrU:
  2177  			c.emit(
  2178  				NewOperationV128Shr(ShapeI32x4, false),
  2179  			)
  2180  		case wasm.OpcodeVecI64x2Shl:
  2181  			c.emit(
  2182  				NewOperationV128Shl(ShapeI64x2),
  2183  			)
  2184  		case wasm.OpcodeVecI64x2ShrS:
  2185  			c.emit(
  2186  				NewOperationV128Shr(ShapeI64x2, true),
  2187  			)
  2188  		case wasm.OpcodeVecI64x2ShrU:
  2189  			c.emit(
  2190  				NewOperationV128Shr(ShapeI64x2, false),
  2191  			)
  2192  		case wasm.OpcodeVecI8x16Eq:
  2193  			c.emit(
  2194  				NewOperationV128Cmp(V128CmpTypeI8x16Eq),
  2195  			)
  2196  		case wasm.OpcodeVecI8x16Ne:
  2197  			c.emit(
  2198  				NewOperationV128Cmp(V128CmpTypeI8x16Ne),
  2199  			)
  2200  		case wasm.OpcodeVecI8x16LtS:
  2201  			c.emit(
  2202  				NewOperationV128Cmp(V128CmpTypeI8x16LtS),
  2203  			)
  2204  		case wasm.OpcodeVecI8x16LtU:
  2205  			c.emit(
  2206  				NewOperationV128Cmp(V128CmpTypeI8x16LtU),
  2207  			)
  2208  		case wasm.OpcodeVecI8x16GtS:
  2209  			c.emit(
  2210  				NewOperationV128Cmp(V128CmpTypeI8x16GtS),
  2211  			)
  2212  		case wasm.OpcodeVecI8x16GtU:
  2213  			c.emit(
  2214  				NewOperationV128Cmp(V128CmpTypeI8x16GtU),
  2215  			)
  2216  		case wasm.OpcodeVecI8x16LeS:
  2217  			c.emit(
  2218  				NewOperationV128Cmp(V128CmpTypeI8x16LeS),
  2219  			)
  2220  		case wasm.OpcodeVecI8x16LeU:
  2221  			c.emit(
  2222  				NewOperationV128Cmp(V128CmpTypeI8x16LeU),
  2223  			)
  2224  		case wasm.OpcodeVecI8x16GeS:
  2225  			c.emit(
  2226  				NewOperationV128Cmp(V128CmpTypeI8x16GeS),
  2227  			)
  2228  		case wasm.OpcodeVecI8x16GeU:
  2229  			c.emit(
  2230  				NewOperationV128Cmp(V128CmpTypeI8x16GeU),
  2231  			)
  2232  		case wasm.OpcodeVecI16x8Eq:
  2233  			c.emit(
  2234  				NewOperationV128Cmp(V128CmpTypeI16x8Eq),
  2235  			)
  2236  		case wasm.OpcodeVecI16x8Ne:
  2237  			c.emit(
  2238  				NewOperationV128Cmp(V128CmpTypeI16x8Ne),
  2239  			)
  2240  		case wasm.OpcodeVecI16x8LtS:
  2241  			c.emit(
  2242  				NewOperationV128Cmp(V128CmpTypeI16x8LtS),
  2243  			)
  2244  		case wasm.OpcodeVecI16x8LtU:
  2245  			c.emit(
  2246  				NewOperationV128Cmp(V128CmpTypeI16x8LtU),
  2247  			)
  2248  		case wasm.OpcodeVecI16x8GtS:
  2249  			c.emit(
  2250  				NewOperationV128Cmp(V128CmpTypeI16x8GtS),
  2251  			)
  2252  		case wasm.OpcodeVecI16x8GtU:
  2253  			c.emit(
  2254  				NewOperationV128Cmp(V128CmpTypeI16x8GtU),
  2255  			)
  2256  		case wasm.OpcodeVecI16x8LeS:
  2257  			c.emit(
  2258  				NewOperationV128Cmp(V128CmpTypeI16x8LeS),
  2259  			)
  2260  		case wasm.OpcodeVecI16x8LeU:
  2261  			c.emit(
  2262  				NewOperationV128Cmp(V128CmpTypeI16x8LeU),
  2263  			)
  2264  		case wasm.OpcodeVecI16x8GeS:
  2265  			c.emit(
  2266  				NewOperationV128Cmp(V128CmpTypeI16x8GeS),
  2267  			)
  2268  		case wasm.OpcodeVecI16x8GeU:
  2269  			c.emit(
  2270  				NewOperationV128Cmp(V128CmpTypeI16x8GeU),
  2271  			)
  2272  		case wasm.OpcodeVecI32x4Eq:
  2273  			c.emit(
  2274  				NewOperationV128Cmp(V128CmpTypeI32x4Eq),
  2275  			)
  2276  		case wasm.OpcodeVecI32x4Ne:
  2277  			c.emit(
  2278  				NewOperationV128Cmp(V128CmpTypeI32x4Ne),
  2279  			)
  2280  		case wasm.OpcodeVecI32x4LtS:
  2281  			c.emit(
  2282  				NewOperationV128Cmp(V128CmpTypeI32x4LtS),
  2283  			)
  2284  		case wasm.OpcodeVecI32x4LtU:
  2285  			c.emit(
  2286  				NewOperationV128Cmp(V128CmpTypeI32x4LtU),
  2287  			)
  2288  		case wasm.OpcodeVecI32x4GtS:
  2289  			c.emit(
  2290  				NewOperationV128Cmp(V128CmpTypeI32x4GtS),
  2291  			)
  2292  		case wasm.OpcodeVecI32x4GtU:
  2293  			c.emit(
  2294  				NewOperationV128Cmp(V128CmpTypeI32x4GtU),
  2295  			)
  2296  		case wasm.OpcodeVecI32x4LeS:
  2297  			c.emit(
  2298  				NewOperationV128Cmp(V128CmpTypeI32x4LeS),
  2299  			)
  2300  		case wasm.OpcodeVecI32x4LeU:
  2301  			c.emit(
  2302  				NewOperationV128Cmp(V128CmpTypeI32x4LeU),
  2303  			)
  2304  		case wasm.OpcodeVecI32x4GeS:
  2305  			c.emit(
  2306  				NewOperationV128Cmp(V128CmpTypeI32x4GeS),
  2307  			)
  2308  		case wasm.OpcodeVecI32x4GeU:
  2309  			c.emit(
  2310  				NewOperationV128Cmp(V128CmpTypeI32x4GeU),
  2311  			)
  2312  		case wasm.OpcodeVecI64x2Eq:
  2313  			c.emit(
  2314  				NewOperationV128Cmp(V128CmpTypeI64x2Eq),
  2315  			)
  2316  		case wasm.OpcodeVecI64x2Ne:
  2317  			c.emit(
  2318  				NewOperationV128Cmp(V128CmpTypeI64x2Ne),
  2319  			)
  2320  		case wasm.OpcodeVecI64x2LtS:
  2321  			c.emit(
  2322  				NewOperationV128Cmp(V128CmpTypeI64x2LtS),
  2323  			)
  2324  		case wasm.OpcodeVecI64x2GtS:
  2325  			c.emit(
  2326  				NewOperationV128Cmp(V128CmpTypeI64x2GtS),
  2327  			)
  2328  		case wasm.OpcodeVecI64x2LeS:
  2329  			c.emit(
  2330  				NewOperationV128Cmp(V128CmpTypeI64x2LeS),
  2331  			)
  2332  		case wasm.OpcodeVecI64x2GeS:
  2333  			c.emit(
  2334  				NewOperationV128Cmp(V128CmpTypeI64x2GeS),
  2335  			)
  2336  		case wasm.OpcodeVecF32x4Eq:
  2337  			c.emit(
  2338  				NewOperationV128Cmp(V128CmpTypeF32x4Eq),
  2339  			)
  2340  		case wasm.OpcodeVecF32x4Ne:
  2341  			c.emit(
  2342  				NewOperationV128Cmp(V128CmpTypeF32x4Ne),
  2343  			)
  2344  		case wasm.OpcodeVecF32x4Lt:
  2345  			c.emit(
  2346  				NewOperationV128Cmp(V128CmpTypeF32x4Lt),
  2347  			)
  2348  		case wasm.OpcodeVecF32x4Gt:
  2349  			c.emit(
  2350  				NewOperationV128Cmp(V128CmpTypeF32x4Gt),
  2351  			)
  2352  		case wasm.OpcodeVecF32x4Le:
  2353  			c.emit(
  2354  				NewOperationV128Cmp(V128CmpTypeF32x4Le),
  2355  			)
  2356  		case wasm.OpcodeVecF32x4Ge:
  2357  			c.emit(
  2358  				NewOperationV128Cmp(V128CmpTypeF32x4Ge),
  2359  			)
  2360  		case wasm.OpcodeVecF64x2Eq:
  2361  			c.emit(
  2362  				NewOperationV128Cmp(V128CmpTypeF64x2Eq),
  2363  			)
  2364  		case wasm.OpcodeVecF64x2Ne:
  2365  			c.emit(
  2366  				NewOperationV128Cmp(V128CmpTypeF64x2Ne),
  2367  			)
  2368  		case wasm.OpcodeVecF64x2Lt:
  2369  			c.emit(
  2370  				NewOperationV128Cmp(V128CmpTypeF64x2Lt),
  2371  			)
  2372  		case wasm.OpcodeVecF64x2Gt:
  2373  			c.emit(
  2374  				NewOperationV128Cmp(V128CmpTypeF64x2Gt),
  2375  			)
  2376  		case wasm.OpcodeVecF64x2Le:
  2377  			c.emit(
  2378  				NewOperationV128Cmp(V128CmpTypeF64x2Le),
  2379  			)
  2380  		case wasm.OpcodeVecF64x2Ge:
  2381  			c.emit(
  2382  				NewOperationV128Cmp(V128CmpTypeF64x2Ge),
  2383  			)
  2384  		case wasm.OpcodeVecI8x16Neg:
  2385  			c.emit(
  2386  				NewOperationV128Neg(ShapeI8x16),
  2387  			)
  2388  		case wasm.OpcodeVecI16x8Neg:
  2389  			c.emit(
  2390  				NewOperationV128Neg(ShapeI16x8),
  2391  			)
  2392  		case wasm.OpcodeVecI32x4Neg:
  2393  			c.emit(
  2394  				NewOperationV128Neg(ShapeI32x4),
  2395  			)
  2396  		case wasm.OpcodeVecI64x2Neg:
  2397  			c.emit(
  2398  				NewOperationV128Neg(ShapeI64x2),
  2399  			)
  2400  		case wasm.OpcodeVecF32x4Neg:
  2401  			c.emit(
  2402  				NewOperationV128Neg(ShapeF32x4),
  2403  			)
  2404  		case wasm.OpcodeVecF64x2Neg:
  2405  			c.emit(
  2406  				NewOperationV128Neg(ShapeF64x2),
  2407  			)
  2408  		case wasm.OpcodeVecI8x16Add:
  2409  			c.emit(
  2410  				NewOperationV128Add(ShapeI8x16),
  2411  			)
  2412  		case wasm.OpcodeVecI16x8Add:
  2413  			c.emit(
  2414  				NewOperationV128Add(ShapeI16x8),
  2415  			)
  2416  		case wasm.OpcodeVecI32x4Add:
  2417  			c.emit(
  2418  				NewOperationV128Add(ShapeI32x4),
  2419  			)
  2420  		case wasm.OpcodeVecI64x2Add:
  2421  			c.emit(
  2422  				NewOperationV128Add(ShapeI64x2),
  2423  			)
  2424  		case wasm.OpcodeVecF32x4Add:
  2425  			c.emit(
  2426  				NewOperationV128Add(ShapeF32x4),
  2427  			)
  2428  		case wasm.OpcodeVecF64x2Add:
  2429  			c.emit(
  2430  				NewOperationV128Add(ShapeF64x2),
  2431  			)
  2432  		case wasm.OpcodeVecI8x16Sub:
  2433  			c.emit(
  2434  				NewOperationV128Sub(ShapeI8x16),
  2435  			)
  2436  		case wasm.OpcodeVecI16x8Sub:
  2437  			c.emit(
  2438  				NewOperationV128Sub(ShapeI16x8),
  2439  			)
  2440  		case wasm.OpcodeVecI32x4Sub:
  2441  			c.emit(
  2442  				NewOperationV128Sub(ShapeI32x4),
  2443  			)
  2444  		case wasm.OpcodeVecI64x2Sub:
  2445  			c.emit(
  2446  				NewOperationV128Sub(ShapeI64x2),
  2447  			)
  2448  		case wasm.OpcodeVecF32x4Sub:
  2449  			c.emit(
  2450  				NewOperationV128Sub(ShapeF32x4),
  2451  			)
  2452  		case wasm.OpcodeVecF64x2Sub:
  2453  			c.emit(
  2454  				NewOperationV128Sub(ShapeF64x2),
  2455  			)
  2456  		case wasm.OpcodeVecI8x16AddSatS:
  2457  			c.emit(
  2458  				NewOperationV128AddSat(ShapeI8x16, true),
  2459  			)
  2460  		case wasm.OpcodeVecI8x16AddSatU:
  2461  			c.emit(
  2462  				NewOperationV128AddSat(ShapeI8x16, false),
  2463  			)
  2464  		case wasm.OpcodeVecI16x8AddSatS:
  2465  			c.emit(
  2466  				NewOperationV128AddSat(ShapeI16x8, true),
  2467  			)
  2468  		case wasm.OpcodeVecI16x8AddSatU:
  2469  			c.emit(
  2470  				NewOperationV128AddSat(ShapeI16x8, false),
  2471  			)
  2472  		case wasm.OpcodeVecI8x16SubSatS:
  2473  			c.emit(
  2474  				NewOperationV128SubSat(ShapeI8x16, true),
  2475  			)
  2476  		case wasm.OpcodeVecI8x16SubSatU:
  2477  			c.emit(
  2478  				NewOperationV128SubSat(ShapeI8x16, false),
  2479  			)
  2480  		case wasm.OpcodeVecI16x8SubSatS:
  2481  			c.emit(
  2482  				NewOperationV128SubSat(ShapeI16x8, true),
  2483  			)
  2484  		case wasm.OpcodeVecI16x8SubSatU:
  2485  			c.emit(
  2486  				NewOperationV128SubSat(ShapeI16x8, false),
  2487  			)
  2488  		case wasm.OpcodeVecI16x8Mul:
  2489  			c.emit(
  2490  				NewOperationV128Mul(ShapeI16x8),
  2491  			)
  2492  		case wasm.OpcodeVecI32x4Mul:
  2493  			c.emit(
  2494  				NewOperationV128Mul(ShapeI32x4),
  2495  			)
  2496  		case wasm.OpcodeVecI64x2Mul:
  2497  			c.emit(
  2498  				NewOperationV128Mul(ShapeI64x2),
  2499  			)
  2500  		case wasm.OpcodeVecF32x4Mul:
  2501  			c.emit(
  2502  				NewOperationV128Mul(ShapeF32x4),
  2503  			)
  2504  		case wasm.OpcodeVecF64x2Mul:
  2505  			c.emit(
  2506  				NewOperationV128Mul(ShapeF64x2),
  2507  			)
  2508  		case wasm.OpcodeVecF32x4Sqrt:
  2509  			c.emit(
  2510  				NewOperationV128Sqrt(ShapeF32x4),
  2511  			)
  2512  		case wasm.OpcodeVecF64x2Sqrt:
  2513  			c.emit(
  2514  				NewOperationV128Sqrt(ShapeF64x2),
  2515  			)
  2516  		case wasm.OpcodeVecF32x4Div:
  2517  			c.emit(
  2518  				NewOperationV128Div(ShapeF32x4),
  2519  			)
  2520  		case wasm.OpcodeVecF64x2Div:
  2521  			c.emit(
  2522  				NewOperationV128Div(ShapeF64x2),
  2523  			)
  2524  		case wasm.OpcodeVecI8x16Abs:
  2525  			c.emit(
  2526  				NewOperationV128Abs(ShapeI8x16),
  2527  			)
  2528  		case wasm.OpcodeVecI8x16Popcnt:
  2529  			c.emit(
  2530  				NewOperationV128Popcnt(ShapeI8x16),
  2531  			)
  2532  		case wasm.OpcodeVecI16x8Abs:
  2533  			c.emit(
  2534  				NewOperationV128Abs(ShapeI16x8),
  2535  			)
  2536  		case wasm.OpcodeVecI32x4Abs:
  2537  			c.emit(
  2538  				NewOperationV128Abs(ShapeI32x4),
  2539  			)
  2540  		case wasm.OpcodeVecI64x2Abs:
  2541  			c.emit(
  2542  				NewOperationV128Abs(ShapeI64x2),
  2543  			)
  2544  		case wasm.OpcodeVecF32x4Abs:
  2545  			c.emit(
  2546  				NewOperationV128Abs(ShapeF32x4),
  2547  			)
  2548  		case wasm.OpcodeVecF64x2Abs:
  2549  			c.emit(
  2550  				NewOperationV128Abs(ShapeF64x2),
  2551  			)
  2552  		case wasm.OpcodeVecI8x16MinS:
  2553  			c.emit(
  2554  				NewOperationV128Min(ShapeI8x16, true),
  2555  			)
  2556  		case wasm.OpcodeVecI8x16MinU:
  2557  			c.emit(
  2558  				NewOperationV128Min(ShapeI8x16, false),
  2559  			)
  2560  		case wasm.OpcodeVecI8x16MaxS:
  2561  			c.emit(
  2562  				NewOperationV128Max(ShapeI8x16, true),
  2563  			)
  2564  		case wasm.OpcodeVecI8x16MaxU:
  2565  			c.emit(
  2566  				NewOperationV128Max(ShapeI8x16, false),
  2567  			)
  2568  		case wasm.OpcodeVecI8x16AvgrU:
  2569  			c.emit(
  2570  				NewOperationV128AvgrU(ShapeI8x16),
  2571  			)
  2572  		case wasm.OpcodeVecI16x8MinS:
  2573  			c.emit(
  2574  				NewOperationV128Min(ShapeI16x8, true),
  2575  			)
  2576  		case wasm.OpcodeVecI16x8MinU:
  2577  			c.emit(
  2578  				NewOperationV128Min(ShapeI16x8, false),
  2579  			)
  2580  		case wasm.OpcodeVecI16x8MaxS:
  2581  			c.emit(
  2582  				NewOperationV128Max(ShapeI16x8, true),
  2583  			)
  2584  		case wasm.OpcodeVecI16x8MaxU:
  2585  			c.emit(
  2586  				NewOperationV128Max(ShapeI16x8, false),
  2587  			)
  2588  		case wasm.OpcodeVecI16x8AvgrU:
  2589  			c.emit(
  2590  				NewOperationV128AvgrU(ShapeI16x8),
  2591  			)
  2592  		case wasm.OpcodeVecI32x4MinS:
  2593  			c.emit(
  2594  				NewOperationV128Min(ShapeI32x4, true),
  2595  			)
  2596  		case wasm.OpcodeVecI32x4MinU:
  2597  			c.emit(
  2598  				NewOperationV128Min(ShapeI32x4, false),
  2599  			)
  2600  		case wasm.OpcodeVecI32x4MaxS:
  2601  			c.emit(
  2602  				NewOperationV128Max(ShapeI32x4, true),
  2603  			)
  2604  		case wasm.OpcodeVecI32x4MaxU:
  2605  			c.emit(
  2606  				NewOperationV128Max(ShapeI32x4, false),
  2607  			)
  2608  		case wasm.OpcodeVecF32x4Min:
  2609  			c.emit(
  2610  				NewOperationV128Min(ShapeF32x4, false),
  2611  			)
  2612  		case wasm.OpcodeVecF32x4Max:
  2613  			c.emit(
  2614  				NewOperationV128Max(ShapeF32x4, false),
  2615  			)
  2616  		case wasm.OpcodeVecF64x2Min:
  2617  			c.emit(
  2618  				NewOperationV128Min(ShapeF64x2, false),
  2619  			)
  2620  		case wasm.OpcodeVecF64x2Max:
  2621  			c.emit(
  2622  				NewOperationV128Max(ShapeF64x2, false),
  2623  			)
  2624  		case wasm.OpcodeVecF32x4Pmin:
  2625  			c.emit(
  2626  				NewOperationV128Pmin(ShapeF32x4),
  2627  			)
  2628  		case wasm.OpcodeVecF32x4Pmax:
  2629  			c.emit(
  2630  				NewOperationV128Pmax(ShapeF32x4),
  2631  			)
  2632  		case wasm.OpcodeVecF64x2Pmin:
  2633  			c.emit(
  2634  				NewOperationV128Pmin(ShapeF64x2),
  2635  			)
  2636  		case wasm.OpcodeVecF64x2Pmax:
  2637  			c.emit(
  2638  				NewOperationV128Pmax(ShapeF64x2),
  2639  			)
  2640  		case wasm.OpcodeVecF32x4Ceil:
  2641  			c.emit(
  2642  				NewOperationV128Ceil(ShapeF32x4),
  2643  			)
  2644  		case wasm.OpcodeVecF32x4Floor:
  2645  			c.emit(
  2646  				NewOperationV128Floor(ShapeF32x4),
  2647  			)
  2648  		case wasm.OpcodeVecF32x4Trunc:
  2649  			c.emit(
  2650  				NewOperationV128Trunc(ShapeF32x4),
  2651  			)
  2652  		case wasm.OpcodeVecF32x4Nearest:
  2653  			c.emit(
  2654  				NewOperationV128Nearest(ShapeF32x4),
  2655  			)
  2656  		case wasm.OpcodeVecF64x2Ceil:
  2657  			c.emit(
  2658  				NewOperationV128Ceil(ShapeF64x2),
  2659  			)
  2660  		case wasm.OpcodeVecF64x2Floor:
  2661  			c.emit(
  2662  				NewOperationV128Floor(ShapeF64x2),
  2663  			)
  2664  		case wasm.OpcodeVecF64x2Trunc:
  2665  			c.emit(
  2666  				NewOperationV128Trunc(ShapeF64x2),
  2667  			)
  2668  		case wasm.OpcodeVecF64x2Nearest:
  2669  			c.emit(
  2670  				NewOperationV128Nearest(ShapeF64x2),
  2671  			)
  2672  		case wasm.OpcodeVecI16x8ExtendLowI8x16S:
  2673  			c.emit(
  2674  				NewOperationV128Extend(ShapeI8x16, true, true),
  2675  			)
  2676  		case wasm.OpcodeVecI16x8ExtendHighI8x16S:
  2677  			c.emit(
  2678  				NewOperationV128Extend(ShapeI8x16, true, false),
  2679  			)
  2680  		case wasm.OpcodeVecI16x8ExtendLowI8x16U:
  2681  			c.emit(
  2682  				NewOperationV128Extend(ShapeI8x16, false, true),
  2683  			)
  2684  		case wasm.OpcodeVecI16x8ExtendHighI8x16U:
  2685  			c.emit(
  2686  				NewOperationV128Extend(ShapeI8x16, false, false),
  2687  			)
  2688  		case wasm.OpcodeVecI32x4ExtendLowI16x8S:
  2689  			c.emit(
  2690  				NewOperationV128Extend(ShapeI16x8, true, true),
  2691  			)
  2692  		case wasm.OpcodeVecI32x4ExtendHighI16x8S:
  2693  			c.emit(
  2694  				NewOperationV128Extend(ShapeI16x8, true, false),
  2695  			)
  2696  		case wasm.OpcodeVecI32x4ExtendLowI16x8U:
  2697  			c.emit(
  2698  				NewOperationV128Extend(ShapeI16x8, false, true),
  2699  			)
  2700  		case wasm.OpcodeVecI32x4ExtendHighI16x8U:
  2701  			c.emit(
  2702  				NewOperationV128Extend(ShapeI16x8, false, false),
  2703  			)
  2704  		case wasm.OpcodeVecI64x2ExtendLowI32x4S:
  2705  			c.emit(
  2706  				NewOperationV128Extend(ShapeI32x4, true, true),
  2707  			)
  2708  		case wasm.OpcodeVecI64x2ExtendHighI32x4S:
  2709  			c.emit(
  2710  				NewOperationV128Extend(ShapeI32x4, true, false),
  2711  			)
  2712  		case wasm.OpcodeVecI64x2ExtendLowI32x4U:
  2713  			c.emit(
  2714  				NewOperationV128Extend(ShapeI32x4, false, true),
  2715  			)
  2716  		case wasm.OpcodeVecI64x2ExtendHighI32x4U:
  2717  			c.emit(
  2718  				NewOperationV128Extend(ShapeI32x4, false, false),
  2719  			)
  2720  		case wasm.OpcodeVecI16x8Q15mulrSatS:
  2721  			c.emit(
  2722  				NewOperationV128Q15mulrSatS(),
  2723  			)
  2724  		case wasm.OpcodeVecI16x8ExtMulLowI8x16S:
  2725  			c.emit(
  2726  				NewOperationV128ExtMul(ShapeI8x16, true, true),
  2727  			)
  2728  		case wasm.OpcodeVecI16x8ExtMulHighI8x16S:
  2729  			c.emit(
  2730  				NewOperationV128ExtMul(ShapeI8x16, true, false),
  2731  			)
  2732  		case wasm.OpcodeVecI16x8ExtMulLowI8x16U:
  2733  			c.emit(
  2734  				NewOperationV128ExtMul(ShapeI8x16, false, true),
  2735  			)
  2736  		case wasm.OpcodeVecI16x8ExtMulHighI8x16U:
  2737  			c.emit(
  2738  				NewOperationV128ExtMul(ShapeI8x16, false, false),
  2739  			)
  2740  		case wasm.OpcodeVecI32x4ExtMulLowI16x8S:
  2741  			c.emit(
  2742  				NewOperationV128ExtMul(ShapeI16x8, true, true),
  2743  			)
  2744  		case wasm.OpcodeVecI32x4ExtMulHighI16x8S:
  2745  			c.emit(
  2746  				NewOperationV128ExtMul(ShapeI16x8, true, false),
  2747  			)
  2748  		case wasm.OpcodeVecI32x4ExtMulLowI16x8U:
  2749  			c.emit(
  2750  				NewOperationV128ExtMul(ShapeI16x8, false, true),
  2751  			)
  2752  		case wasm.OpcodeVecI32x4ExtMulHighI16x8U:
  2753  			c.emit(
  2754  				NewOperationV128ExtMul(ShapeI16x8, false, false),
  2755  			)
  2756  		case wasm.OpcodeVecI64x2ExtMulLowI32x4S:
  2757  			c.emit(
  2758  				NewOperationV128ExtMul(ShapeI32x4, true, true),
  2759  			)
  2760  		case wasm.OpcodeVecI64x2ExtMulHighI32x4S:
  2761  			c.emit(
  2762  				NewOperationV128ExtMul(ShapeI32x4, true, false),
  2763  			)
  2764  		case wasm.OpcodeVecI64x2ExtMulLowI32x4U:
  2765  			c.emit(
  2766  				NewOperationV128ExtMul(ShapeI32x4, false, true),
  2767  			)
  2768  		case wasm.OpcodeVecI64x2ExtMulHighI32x4U:
  2769  			c.emit(
  2770  				NewOperationV128ExtMul(ShapeI32x4, false, false),
  2771  			)
  2772  		case wasm.OpcodeVecI16x8ExtaddPairwiseI8x16S:
  2773  			c.emit(
  2774  				NewOperationV128ExtAddPairwise(ShapeI8x16, true),
  2775  			)
  2776  		case wasm.OpcodeVecI16x8ExtaddPairwiseI8x16U:
  2777  			c.emit(
  2778  				NewOperationV128ExtAddPairwise(ShapeI8x16, false),
  2779  			)
  2780  		case wasm.OpcodeVecI32x4ExtaddPairwiseI16x8S:
  2781  			c.emit(
  2782  				NewOperationV128ExtAddPairwise(ShapeI16x8, true),
  2783  			)
  2784  		case wasm.OpcodeVecI32x4ExtaddPairwiseI16x8U:
  2785  			c.emit(
  2786  				NewOperationV128ExtAddPairwise(ShapeI16x8, false),
  2787  			)
  2788  		case wasm.OpcodeVecF64x2PromoteLowF32x4Zero:
  2789  			c.emit(
  2790  				NewOperationV128FloatPromote(),
  2791  			)
  2792  		case wasm.OpcodeVecF32x4DemoteF64x2Zero:
  2793  			c.emit(
  2794  				NewOperationV128FloatDemote(),
  2795  			)
  2796  		case wasm.OpcodeVecF32x4ConvertI32x4S:
  2797  			c.emit(
  2798  				NewOperationV128FConvertFromI(ShapeF32x4, true),
  2799  			)
  2800  		case wasm.OpcodeVecF32x4ConvertI32x4U:
  2801  			c.emit(
  2802  				NewOperationV128FConvertFromI(ShapeF32x4, false),
  2803  			)
  2804  		case wasm.OpcodeVecF64x2ConvertLowI32x4S:
  2805  			c.emit(
  2806  				NewOperationV128FConvertFromI(ShapeF64x2, true),
  2807  			)
  2808  		case wasm.OpcodeVecF64x2ConvertLowI32x4U:
  2809  			c.emit(
  2810  				NewOperationV128FConvertFromI(ShapeF64x2, false),
  2811  			)
  2812  		case wasm.OpcodeVecI32x4DotI16x8S:
  2813  			c.emit(
  2814  				NewOperationV128Dot(),
  2815  			)
  2816  		case wasm.OpcodeVecI8x16NarrowI16x8S:
  2817  			c.emit(
  2818  				NewOperationV128Narrow(ShapeI16x8, true),
  2819  			)
  2820  		case wasm.OpcodeVecI8x16NarrowI16x8U:
  2821  			c.emit(
  2822  				NewOperationV128Narrow(ShapeI16x8, false),
  2823  			)
  2824  		case wasm.OpcodeVecI16x8NarrowI32x4S:
  2825  			c.emit(
  2826  				NewOperationV128Narrow(ShapeI32x4, true),
  2827  			)
  2828  		case wasm.OpcodeVecI16x8NarrowI32x4U:
  2829  			c.emit(
  2830  				NewOperationV128Narrow(ShapeI32x4, false),
  2831  			)
  2832  		case wasm.OpcodeVecI32x4TruncSatF32x4S:
  2833  			c.emit(
  2834  				NewOperationV128ITruncSatFromF(ShapeF32x4, true),
  2835  			)
  2836  		case wasm.OpcodeVecI32x4TruncSatF32x4U:
  2837  			c.emit(
  2838  				NewOperationV128ITruncSatFromF(ShapeF32x4, false),
  2839  			)
  2840  		case wasm.OpcodeVecI32x4TruncSatF64x2SZero:
  2841  			c.emit(
  2842  				NewOperationV128ITruncSatFromF(ShapeF64x2, true),
  2843  			)
  2844  		case wasm.OpcodeVecI32x4TruncSatF64x2UZero:
  2845  			c.emit(
  2846  				NewOperationV128ITruncSatFromF(ShapeF64x2, false),
  2847  			)
  2848  		default:
  2849  			return fmt.Errorf("unsupported vector instruction in wazeroir: %s", wasm.VectorInstructionName(vecOp))
  2850  		}
  2851  	default:
  2852  		return fmt.Errorf("unsupported instruction in wazeroir: 0x%x", op)
  2853  	}
  2854  
  2855  	// Move the program counter to point to the next instruction.
  2856  	c.pc++
  2857  	return nil
  2858  }
  2859  
  2860  func (c *Compiler) nextFrameID() (id uint32) {
  2861  	id = c.currentFrameID + 1
  2862  	c.currentFrameID++
  2863  	return
  2864  }
  2865  
  2866  func (c *Compiler) applyToStack(opcode wasm.Opcode) (index uint32, err error) {
  2867  	switch opcode {
  2868  	case
  2869  		// These are the opcodes that is coupled with "index" immediate
  2870  		// and it DOES affect the signature of opcode.
  2871  		wasm.OpcodeCall,
  2872  		wasm.OpcodeCallIndirect,
  2873  		wasm.OpcodeLocalGet,
  2874  		wasm.OpcodeLocalSet,
  2875  		wasm.OpcodeLocalTee,
  2876  		wasm.OpcodeGlobalGet,
  2877  		wasm.OpcodeGlobalSet:
  2878  		// Assumes that we are at the opcode now so skip it before read immediates.
  2879  		v, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  2880  		if err != nil {
  2881  			return 0, fmt.Errorf("reading immediates: %w", err)
  2882  		}
  2883  		c.pc += num
  2884  		index = v
  2885  	default:
  2886  		// Note that other opcodes are free of index
  2887  		// as it doesn't affect the signature of opt code.
  2888  		// In other words, the "index" argument of wasmOpcodeSignature
  2889  		// is ignored there.
  2890  	}
  2891  
  2892  	if c.unreachableState.on {
  2893  		return 0, nil
  2894  	}
  2895  
  2896  	// Retrieve the signature of the opcode.
  2897  	s, err := c.wasmOpcodeSignature(opcode, index)
  2898  	if err != nil {
  2899  		return 0, err
  2900  	}
  2901  
  2902  	// Manipulate the stack according to the signature.
  2903  	// Note that the following algorithm assumes that
  2904  	// the unknown type is unique in the signature,
  2905  	// and is determined by the actual type on the stack.
  2906  	// The determined type is stored in this typeParam.
  2907  	var typeParam UnsignedType
  2908  	var typeParamFound bool
  2909  	for i := range s.in {
  2910  		want := s.in[len(s.in)-1-i]
  2911  		actual := c.stackPop()
  2912  		if want == UnsignedTypeUnknown && typeParamFound {
  2913  			want = typeParam
  2914  		} else if want == UnsignedTypeUnknown {
  2915  			want = actual
  2916  			typeParam = want
  2917  			typeParamFound = true
  2918  		}
  2919  		if want != actual {
  2920  			return 0, fmt.Errorf("input signature mismatch: want %s but have %s", want, actual)
  2921  		}
  2922  	}
  2923  
  2924  	for _, target := range s.out {
  2925  		if target == UnsignedTypeUnknown && !typeParamFound {
  2926  			return 0, fmt.Errorf("cannot determine type of unknown result")
  2927  		} else if target == UnsignedTypeUnknown {
  2928  			c.stackPush(typeParam)
  2929  		} else {
  2930  			c.stackPush(target)
  2931  		}
  2932  	}
  2933  
  2934  	return index, nil
  2935  }
  2936  
  2937  func (c *Compiler) stackPeek() (ret UnsignedType) {
  2938  	ret = c.stack[len(c.stack)-1]
  2939  	return
  2940  }
  2941  
  2942  func (c *Compiler) stackPop() (ret UnsignedType) {
  2943  	// No need to check stack bound
  2944  	// as we can assume that all the operations
  2945  	// are valid thanks to validateFunction
  2946  	// at module validation phase.
  2947  	ret = c.stack[len(c.stack)-1]
  2948  	c.stack = c.stack[:len(c.stack)-1]
  2949  	return
  2950  }
  2951  
  2952  func (c *Compiler) stackPush(ts UnsignedType) {
  2953  	c.stack = append(c.stack, ts)
  2954  }
  2955  
  2956  // emit adds the operations into the result.
  2957  func (c *Compiler) emit(op UnionOperation) {
  2958  	if !c.unreachableState.on {
  2959  		switch op.Kind {
  2960  		case OperationKindDrop:
  2961  			// If the drop range is nil,
  2962  			// we could remove such operations.
  2963  			// That happens when drop operation is unnecessary.
  2964  			// i.e. when there's no need to adjust stack before jmp.
  2965  			if int64(op.U1) == -1 {
  2966  				return
  2967  			}
  2968  		}
  2969  		c.result.Operations = append(c.result.Operations, op)
  2970  		if c.needSourceOffset {
  2971  			c.result.IROperationSourceOffsetsInWasmBinary = append(c.result.IROperationSourceOffsetsInWasmBinary,
  2972  				c.currentOpPC+c.bodyOffsetInCodeSection)
  2973  		}
  2974  	}
  2975  }
  2976  
  2977  // Emit const expression with default values of the given type.
  2978  func (c *Compiler) emitDefaultValue(t wasm.ValueType) {
  2979  	switch t {
  2980  	case wasm.ValueTypeI32:
  2981  		c.stackPush(UnsignedTypeI32)
  2982  		c.emit(NewOperationConstI32(0))
  2983  	case wasm.ValueTypeI64, wasm.ValueTypeExternref, wasm.ValueTypeFuncref:
  2984  		c.stackPush(UnsignedTypeI64)
  2985  		c.emit(NewOperationConstI64(0))
  2986  	case wasm.ValueTypeF32:
  2987  		c.stackPush(UnsignedTypeF32)
  2988  		c.emit(NewOperationConstF32(0))
  2989  	case wasm.ValueTypeF64:
  2990  		c.stackPush(UnsignedTypeF64)
  2991  		c.emit(NewOperationConstF64(0))
  2992  	case wasm.ValueTypeV128:
  2993  		c.stackPush(UnsignedTypeV128)
  2994  		c.emit(NewOperationV128Const(0, 0))
  2995  	}
  2996  }
  2997  
  2998  // Returns the "depth" (starting from top of the stack)
  2999  // of the n-th local.
  3000  func (c *Compiler) localDepth(index wasm.Index) int {
  3001  	height := c.localIndexToStackHeightInUint64[index]
  3002  	return c.stackLenInUint64(len(c.stack)) - 1 - int(height)
  3003  }
  3004  
  3005  func (c *Compiler) localType(index wasm.Index) (t wasm.ValueType) {
  3006  	if params := uint32(len(c.sig.Params)); index < params {
  3007  		t = c.sig.Params[index]
  3008  	} else {
  3009  		t = c.localTypes[index-params]
  3010  	}
  3011  	return
  3012  }
  3013  
  3014  // getFrameDropRange returns the range (starting from top of the stack) that spans across the (uint64) stack. The range is
  3015  // supposed to be dropped from the stack when the given frame exists or branch into it.
  3016  //
  3017  // * frame is the control frame which the call-site is trying to branch into or exit.
  3018  // * isEnd true if the call-site is handling wasm.OpcodeEnd.
  3019  func (c *Compiler) getFrameDropRange(frame *controlFrame, isEnd bool) InclusiveRange {
  3020  	var start int
  3021  	if !isEnd && frame.kind == controlFrameKindLoop {
  3022  		// If this is not End and the call-site is trying to branch into the Loop control frame,
  3023  		// we have to Start executing from the beginning of the loop block.
  3024  		// Therefore, we have to pass the inputs to the frame.
  3025  		start = frame.blockType.ParamNumInUint64
  3026  	} else {
  3027  		start = frame.blockType.ResultNumInUint64
  3028  	}
  3029  	var end int
  3030  	if frame.kind == controlFrameKindFunction {
  3031  		// On the function return, we eliminate all the contents on the stack
  3032  		// including locals (existing below of frame.originalStackLen)
  3033  		end = c.stackLenInUint64(len(c.stack)) - 1
  3034  	} else {
  3035  		end = c.stackLenInUint64(len(c.stack)) - 1 - c.stackLenInUint64(frame.originalStackLenWithoutParam)
  3036  	}
  3037  	if start <= end {
  3038  		return InclusiveRange{Start: int32(start), End: int32(end)}
  3039  	} else {
  3040  		return NopInclusiveRange
  3041  	}
  3042  }
  3043  
  3044  func (c *Compiler) stackLenInUint64(ceil int) (ret int) {
  3045  	for i := 0; i < ceil; i++ {
  3046  		if c.stack[i] == UnsignedTypeV128 {
  3047  			ret += 2
  3048  		} else {
  3049  			ret++
  3050  		}
  3051  	}
  3052  	return
  3053  }
  3054  
  3055  func (c *Compiler) readMemoryArg(tag string) (MemoryArg, error) {
  3056  	c.result.UsesMemory = true
  3057  	alignment, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  3058  	if err != nil {
  3059  		return MemoryArg{}, fmt.Errorf("reading alignment for %s: %w", tag, err)
  3060  	}
  3061  	c.pc += num
  3062  	offset, num, err := leb128.LoadUint32(c.body[c.pc+1:])
  3063  	if err != nil {
  3064  		return MemoryArg{}, fmt.Errorf("reading offset for %s: %w", tag, err)
  3065  	}
  3066  	c.pc += num
  3067  	return MemoryArg{Offset: offset, Alignment: alignment}, nil
  3068  }
  3069  

View as plain text