compiler.go

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