func_validation.go

   1package wasm
   2
   3import (
   4	"bytes"
   5	"errors"
   6	"fmt"
   7	"strconv"
   8	"strings"
   9
  10	"github.com/tetratelabs/wazero/api"
  11	"github.com/tetratelabs/wazero/experimental"
  12	"github.com/tetratelabs/wazero/internal/leb128"
  13)
  14
  15// The wazero specific limitation described at RATIONALE.md.
  16const maximumValuesOnStack = 1 << 27
  17
  18// validateFunction validates the instruction sequence of a function.
  19// following the specification https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#instructions%E2%91%A2.
  20//
  21// * idx is the index in the FunctionSection
  22// * functions are the function index, which is prefixed by imports. The value is the TypeSection index.
  23// * globals are the global index, which is prefixed by imports.
  24// * memory is the potentially imported memory and can be nil.
  25// * table is the potentially imported table and can be nil.
  26// * declaredFunctionIndexes is the set of function indexes declared by declarative element segments which can be acceed by OpcodeRefFunc instruction.
  27//
  28// Returns an error if the instruction sequence is not valid,
  29// or potentially it can exceed the maximum number of values on the stack.
  30func (m *Module) validateFunction(sts *stacks, enabledFeatures api.CoreFeatures, idx Index, functions []Index,
  31	globals []GlobalType, memory *Memory, tables []Table, declaredFunctionIndexes map[Index]struct{}, br *bytes.Reader,
  32) error {
  33	return m.validateFunctionWithMaxStackValues(sts, enabledFeatures, idx, functions, globals, memory, tables, maximumValuesOnStack, declaredFunctionIndexes, br)
  34}
  35
  36func readMemArg(pc uint64, body []byte) (align, offset uint32, read uint64, err error) {
  37	align, num, err := leb128.LoadUint32(body[pc:])
  38	if err != nil {
  39		err = fmt.Errorf("read memory align: %v", err)
  40		return
  41	}
  42	read += num
  43
  44	offset, num, err = leb128.LoadUint32(body[pc+num:])
  45	if err != nil {
  46		err = fmt.Errorf("read memory offset: %v", err)
  47		return
  48	}
  49
  50	read += num
  51	return align, offset, read, nil
  52}
  53
  54// validateFunctionWithMaxStackValues is like validateFunction, but allows overriding maxStackValues for testing.
  55//
  56// * stacks is to track the state of Wasm value and control frame stacks at anypoint of execution, and reused to reduce allocation.
  57// * maxStackValues is the maximum height of values stack which the target is allowed to reach.
  58func (m *Module) validateFunctionWithMaxStackValues(
  59	sts *stacks,
  60	enabledFeatures api.CoreFeatures,
  61	idx Index,
  62	functions []Index,
  63	globals []GlobalType,
  64	memory *Memory,
  65	tables []Table,
  66	maxStackValues int,
  67	declaredFunctionIndexes map[Index]struct{},
  68	br *bytes.Reader,
  69) error {
  70	functionType := &m.TypeSection[m.FunctionSection[idx]]
  71	code := &m.CodeSection[idx]
  72	body := code.Body
  73	localTypes := code.LocalTypes
  74
  75	sts.reset(functionType)
  76	valueTypeStack := &sts.vs
  77	// We start with the outermost control block which is for function return if the code branches into it.
  78	controlBlockStack := &sts.cs
  79
  80	// Now start walking through all the instructions in the body while tracking
  81	// control blocks and value types to check the validity of all instructions.
  82	for pc := uint64(0); pc < uint64(len(body)); pc++ {
  83		op := body[pc]
  84		if false {
  85			var instName string
  86			if op == OpcodeMiscPrefix {
  87				instName = MiscInstructionName(body[pc+1])
  88			} else if op == OpcodeVecPrefix {
  89				instName = VectorInstructionName(body[pc+1])
  90			} else if op == OpcodeAtomicPrefix {
  91				instName = AtomicInstructionName(body[pc+1])
  92			} else {
  93				instName = InstructionName(op)
  94			}
  95			fmt.Printf("handling %s, stack=%s, blocks: %v\n", instName, valueTypeStack.stack, controlBlockStack)
  96		}
  97
  98		if len(controlBlockStack.stack) == 0 {
  99			return fmt.Errorf("unexpected end of function at pc=%#x", pc)
 100		}
 101
 102		if OpcodeI32Load <= op && op <= OpcodeI64Store32 {
 103			if memory == nil {
 104				return fmt.Errorf("memory must exist for %s", InstructionName(op))
 105			}
 106			pc++
 107			align, _, read, err := readMemArg(pc, body)
 108			if err != nil {
 109				return err
 110			}
 111			pc += read - 1
 112			switch op {
 113			case OpcodeI32Load:
 114				if 1<<align > 32/8 {
 115					return fmt.Errorf("invalid memory alignment")
 116				}
 117				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 118					return err
 119				}
 120				valueTypeStack.push(ValueTypeI32)
 121			case OpcodeF32Load:
 122				if 1<<align > 32/8 {
 123					return fmt.Errorf("invalid memory alignment")
 124				}
 125				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 126					return err
 127				}
 128				valueTypeStack.push(ValueTypeF32)
 129			case OpcodeI32Store:
 130				if 1<<align > 32/8 {
 131					return fmt.Errorf("invalid memory alignment")
 132				}
 133				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 134					return err
 135				}
 136				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 137					return err
 138				}
 139			case OpcodeF32Store:
 140				if 1<<align > 32/8 {
 141					return fmt.Errorf("invalid memory alignment")
 142				}
 143				if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
 144					return err
 145				}
 146				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 147					return err
 148				}
 149			case OpcodeI64Load:
 150				if 1<<align > 64/8 {
 151					return fmt.Errorf("invalid memory alignment")
 152				}
 153				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 154					return err
 155				}
 156				valueTypeStack.push(ValueTypeI64)
 157			case OpcodeF64Load:
 158				if 1<<align > 64/8 {
 159					return fmt.Errorf("invalid memory alignment")
 160				}
 161				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 162					return err
 163				}
 164				valueTypeStack.push(ValueTypeF64)
 165			case OpcodeI64Store:
 166				if 1<<align > 64/8 {
 167					return fmt.Errorf("invalid memory alignment")
 168				}
 169				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
 170					return err
 171				}
 172				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 173					return err
 174				}
 175			case OpcodeF64Store:
 176				if 1<<align > 64/8 {
 177					return fmt.Errorf("invalid memory alignment")
 178				}
 179				if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
 180					return err
 181				}
 182				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 183					return err
 184				}
 185			case OpcodeI32Load8S:
 186				if 1<<align > 1 {
 187					return fmt.Errorf("invalid memory alignment")
 188				}
 189				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 190					return err
 191				}
 192				valueTypeStack.push(ValueTypeI32)
 193			case OpcodeI32Load8U:
 194				if 1<<align > 1 {
 195					return fmt.Errorf("invalid memory alignment")
 196				}
 197				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 198					return err
 199				}
 200				valueTypeStack.push(ValueTypeI32)
 201			case OpcodeI64Load8S, OpcodeI64Load8U:
 202				if 1<<align > 1 {
 203					return fmt.Errorf("invalid memory alignment")
 204				}
 205				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 206					return err
 207				}
 208				valueTypeStack.push(ValueTypeI64)
 209			case OpcodeI32Store8:
 210				if 1<<align > 1 {
 211					return fmt.Errorf("invalid memory alignment")
 212				}
 213				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 214					return err
 215				}
 216				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 217					return err
 218				}
 219			case OpcodeI64Store8:
 220				if 1<<align > 1 {
 221					return fmt.Errorf("invalid memory alignment")
 222				}
 223				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
 224					return err
 225				}
 226				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 227					return err
 228				}
 229			case OpcodeI32Load16S, OpcodeI32Load16U:
 230				if 1<<align > 16/8 {
 231					return fmt.Errorf("invalid memory alignment")
 232				}
 233				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 234					return err
 235				}
 236				valueTypeStack.push(ValueTypeI32)
 237			case OpcodeI64Load16S, OpcodeI64Load16U:
 238				if 1<<align > 16/8 {
 239					return fmt.Errorf("invalid memory alignment")
 240				}
 241				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 242					return err
 243				}
 244				valueTypeStack.push(ValueTypeI64)
 245			case OpcodeI32Store16:
 246				if 1<<align > 16/8 {
 247					return fmt.Errorf("invalid memory alignment")
 248				}
 249				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 250					return err
 251				}
 252				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 253					return err
 254				}
 255			case OpcodeI64Store16:
 256				if 1<<align > 16/8 {
 257					return fmt.Errorf("invalid memory alignment")
 258				}
 259				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
 260					return err
 261				}
 262				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 263					return err
 264				}
 265			case OpcodeI64Load32S, OpcodeI64Load32U:
 266				if 1<<align > 32/8 {
 267					return fmt.Errorf("invalid memory alignment")
 268				}
 269				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 270					return err
 271				}
 272				valueTypeStack.push(ValueTypeI64)
 273			case OpcodeI64Store32:
 274				if 1<<align > 32/8 {
 275					return fmt.Errorf("invalid memory alignment")
 276				}
 277				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
 278					return err
 279				}
 280				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 281					return err
 282				}
 283			}
 284		} else if OpcodeMemorySize <= op && op <= OpcodeMemoryGrow {
 285			if memory == nil {
 286				return fmt.Errorf("memory must exist for %s", InstructionName(op))
 287			}
 288			pc++
 289			val, num, err := leb128.LoadUint32(body[pc:])
 290			if err != nil {
 291				return fmt.Errorf("read immediate: %v", err)
 292			}
 293			if val != 0 || num != 1 {
 294				return fmt.Errorf("memory instruction reserved bytes not zero with 1 byte")
 295			}
 296			switch Opcode(op) {
 297			case OpcodeMemoryGrow:
 298				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 299					return err
 300				}
 301				valueTypeStack.push(ValueTypeI32)
 302			case OpcodeMemorySize:
 303				valueTypeStack.push(ValueTypeI32)
 304			}
 305			pc += num - 1
 306		} else if OpcodeI32Const <= op && op <= OpcodeF64Const {
 307			pc++
 308			switch Opcode(op) {
 309			case OpcodeI32Const:
 310				_, num, err := leb128.LoadInt32(body[pc:])
 311				if err != nil {
 312					return fmt.Errorf("read i32 immediate: %s", err)
 313				}
 314				pc += num - 1
 315				valueTypeStack.push(ValueTypeI32)
 316			case OpcodeI64Const:
 317				_, num, err := leb128.LoadInt64(body[pc:])
 318				if err != nil {
 319					return fmt.Errorf("read i64 immediate: %v", err)
 320				}
 321				valueTypeStack.push(ValueTypeI64)
 322				pc += num - 1
 323			case OpcodeF32Const:
 324				valueTypeStack.push(ValueTypeF32)
 325				pc += 3
 326			case OpcodeF64Const:
 327				valueTypeStack.push(ValueTypeF64)
 328				pc += 7
 329			}
 330		} else if OpcodeLocalGet <= op && op <= OpcodeGlobalSet {
 331			pc++
 332			index, num, err := leb128.LoadUint32(body[pc:])
 333			if err != nil {
 334				return fmt.Errorf("read immediate: %v", err)
 335			}
 336			pc += num - 1
 337			switch op {
 338			case OpcodeLocalGet:
 339				inputLen := uint32(len(functionType.Params))
 340				if l := uint32(len(localTypes)) + inputLen; index >= l {
 341					return fmt.Errorf("invalid local index for %s %d >= %d(=len(locals)+len(parameters))",
 342						OpcodeLocalGetName, index, l)
 343				}
 344				if index < inputLen {
 345					valueTypeStack.push(functionType.Params[index])
 346				} else {
 347					valueTypeStack.push(localTypes[index-inputLen])
 348				}
 349			case OpcodeLocalSet:
 350				inputLen := uint32(len(functionType.Params))
 351				if l := uint32(len(localTypes)) + inputLen; index >= l {
 352					return fmt.Errorf("invalid local index for %s %d >= %d(=len(locals)+len(parameters))",
 353						OpcodeLocalSetName, index, l)
 354				}
 355				var expType ValueType
 356				if index < inputLen {
 357					expType = functionType.Params[index]
 358				} else {
 359					expType = localTypes[index-inputLen]
 360				}
 361				if err := valueTypeStack.popAndVerifyType(expType); err != nil {
 362					return err
 363				}
 364			case OpcodeLocalTee:
 365				inputLen := uint32(len(functionType.Params))
 366				if l := uint32(len(localTypes)) + inputLen; index >= l {
 367					return fmt.Errorf("invalid local index for %s %d >= %d(=len(locals)+len(parameters))",
 368						OpcodeLocalTeeName, index, l)
 369				}
 370				var expType ValueType
 371				if index < inputLen {
 372					expType = functionType.Params[index]
 373				} else {
 374					expType = localTypes[index-inputLen]
 375				}
 376				if err := valueTypeStack.popAndVerifyType(expType); err != nil {
 377					return err
 378				}
 379				valueTypeStack.push(expType)
 380			case OpcodeGlobalGet:
 381				if index >= uint32(len(globals)) {
 382					return fmt.Errorf("invalid index for %s", OpcodeGlobalGetName)
 383				}
 384				valueTypeStack.push(globals[index].ValType)
 385			case OpcodeGlobalSet:
 386				if index >= uint32(len(globals)) {
 387					return fmt.Errorf("invalid global index")
 388				} else if !globals[index].Mutable {
 389					return fmt.Errorf("%s when not mutable", OpcodeGlobalSetName)
 390				} else if err := valueTypeStack.popAndVerifyType(
 391					globals[index].ValType); err != nil {
 392					return err
 393				}
 394			}
 395		} else if op == OpcodeBr {
 396			pc++
 397			index, num, err := leb128.LoadUint32(body[pc:])
 398			if err != nil {
 399				return fmt.Errorf("read immediate: %v", err)
 400			} else if int(index) >= len(controlBlockStack.stack) {
 401				return fmt.Errorf("invalid %s operation: index out of range", OpcodeBrName)
 402			}
 403			pc += num - 1
 404			// Check type soundness.
 405			target := &controlBlockStack.stack[len(controlBlockStack.stack)-int(index)-1]
 406			var targetResultType []ValueType
 407			if target.op == OpcodeLoop {
 408				targetResultType = target.blockType.Params
 409			} else {
 410				targetResultType = target.blockType.Results
 411			}
 412			if err = valueTypeStack.popResults(op, targetResultType, false); err != nil {
 413				return err
 414			}
 415			// br instruction is stack-polymorphic.
 416			valueTypeStack.unreachable()
 417		} else if op == OpcodeBrIf {
 418			pc++
 419			index, num, err := leb128.LoadUint32(body[pc:])
 420			if err != nil {
 421				return fmt.Errorf("read immediate: %v", err)
 422			} else if int(index) >= len(controlBlockStack.stack) {
 423				return fmt.Errorf(
 424					"invalid ln param given for %s: index=%d with %d for the current label stack length",
 425					OpcodeBrIfName, index, len(controlBlockStack.stack))
 426			}
 427			pc += num - 1
 428			if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 429				return fmt.Errorf("cannot pop the required operand for %s", OpcodeBrIfName)
 430			}
 431			// Check type soundness.
 432			target := &controlBlockStack.stack[len(controlBlockStack.stack)-int(index)-1]
 433			var targetResultType []ValueType
 434			if target.op == OpcodeLoop {
 435				targetResultType = target.blockType.Params
 436			} else {
 437				targetResultType = target.blockType.Results
 438			}
 439			if err := valueTypeStack.popResults(op, targetResultType, false); err != nil {
 440				return err
 441			}
 442			// Push back the result
 443			for _, t := range targetResultType {
 444				valueTypeStack.push(t)
 445			}
 446		} else if op == OpcodeBrTable {
 447			pc++
 448			br.Reset(body[pc:])
 449			nl, num, err := leb128.DecodeUint32(br)
 450			if err != nil {
 451				return fmt.Errorf("read immediate: %w", err)
 452			}
 453
 454			sts.ls = sts.ls[:0]
 455			for i := uint32(0); i < nl; i++ {
 456				l, n, err := leb128.DecodeUint32(br)
 457				if err != nil {
 458					return fmt.Errorf("read immediate: %w", err)
 459				}
 460				num += n
 461				sts.ls = append(sts.ls, l)
 462			}
 463			ln, n, err := leb128.DecodeUint32(br)
 464			if err != nil {
 465				return fmt.Errorf("read immediate: %w", err)
 466			} else if int(ln) >= len(controlBlockStack.stack) {
 467				return fmt.Errorf(
 468					"invalid ln param given for %s: ln=%d with %d for the current label stack length",
 469					OpcodeBrTableName, ln, len(controlBlockStack.stack))
 470			}
 471			pc += n + num - 1
 472			// Check type soundness.
 473			if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 474				return fmt.Errorf("cannot pop the required operand for %s", OpcodeBrTableName)
 475			}
 476			lnLabel := &controlBlockStack.stack[len(controlBlockStack.stack)-1-int(ln)]
 477			var defaultLabelType []ValueType
 478			// Below, we might modify the slice in case of unreachable. Therefore,
 479			// we have to copy the content of block result types, otherwise the original
 480			// function type might result in invalid value types if the block is the outermost label
 481			// which equals the function's type.
 482			if lnLabel.op != OpcodeLoop { // Loop operation doesn't require results since the continuation is the beginning of the loop.
 483				defaultLabelType = make([]ValueType, len(lnLabel.blockType.Results))
 484				copy(defaultLabelType, lnLabel.blockType.Results)
 485			} else {
 486				defaultLabelType = make([]ValueType, len(lnLabel.blockType.Params))
 487				copy(defaultLabelType, lnLabel.blockType.Params)
 488			}
 489
 490			if enabledFeatures.IsEnabled(api.CoreFeatureReferenceTypes) {
 491				// As of reference-types proposal, br_table on unreachable state
 492				// can choose unknown types for expected parameter types for each label.
 493				// https://github.com/WebAssembly/reference-types/pull/116
 494				for i := range defaultLabelType {
 495					index := len(defaultLabelType) - 1 - i
 496					exp := defaultLabelType[index]
 497					actual, err := valueTypeStack.pop()
 498					if err != nil {
 499						return err
 500					}
 501					if actual == valueTypeUnknown {
 502						// Re-assign the expected type to unknown.
 503						defaultLabelType[index] = valueTypeUnknown
 504					} else if actual != exp {
 505						return typeMismatchError(true, OpcodeBrTableName, actual, exp, i)
 506					}
 507				}
 508			} else {
 509				if err = valueTypeStack.popResults(op, defaultLabelType, false); err != nil {
 510					return err
 511				}
 512			}
 513
 514			for _, l := range sts.ls {
 515				if int(l) >= len(controlBlockStack.stack) {
 516					return fmt.Errorf("invalid l param given for %s", OpcodeBrTableName)
 517				}
 518				label := &controlBlockStack.stack[len(controlBlockStack.stack)-1-int(l)]
 519				var tableLabelType []ValueType
 520				if label.op != OpcodeLoop {
 521					tableLabelType = label.blockType.Results
 522				} else {
 523					tableLabelType = label.blockType.Params
 524				}
 525				if len(defaultLabelType) != len(tableLabelType) {
 526					return fmt.Errorf("inconsistent block type length for %s at %d; %v (ln=%d) != %v (l=%d)", OpcodeBrTableName, l, defaultLabelType, ln, tableLabelType, l)
 527				}
 528				for i := range defaultLabelType {
 529					if defaultLabelType[i] != valueTypeUnknown && defaultLabelType[i] != tableLabelType[i] {
 530						return fmt.Errorf("incosistent block type for %s at %d", OpcodeBrTableName, l)
 531					}
 532				}
 533			}
 534
 535			// br_table instruction is stack-polymorphic.
 536			valueTypeStack.unreachable()
 537		} else if op == OpcodeCall {
 538			pc++
 539			index, num, err := leb128.LoadUint32(body[pc:])
 540			if err != nil {
 541				return fmt.Errorf("read immediate: %v", err)
 542			}
 543			pc += num - 1
 544			if int(index) >= len(functions) {
 545				return fmt.Errorf("invalid function index")
 546			}
 547			funcType := &m.TypeSection[functions[index]]
 548			for i := 0; i < len(funcType.Params); i++ {
 549				if err := valueTypeStack.popAndVerifyType(funcType.Params[len(funcType.Params)-1-i]); err != nil {
 550					return fmt.Errorf("type mismatch on %s operation param type: %v", OpcodeCallName, err)
 551				}
 552			}
 553			for _, exp := range funcType.Results {
 554				valueTypeStack.push(exp)
 555			}
 556		} else if op == OpcodeCallIndirect {
 557			pc++
 558			typeIndex, num, err := leb128.LoadUint32(body[pc:])
 559			if err != nil {
 560				return fmt.Errorf("read immediate: %v", err)
 561			}
 562			pc += num
 563
 564			if int(typeIndex) >= len(m.TypeSection) {
 565				return fmt.Errorf("invalid type index at %s: %d", OpcodeCallIndirectName, typeIndex)
 566			}
 567
 568			tableIndex, num, err := leb128.LoadUint32(body[pc:])
 569			if err != nil {
 570				return fmt.Errorf("read table index: %v", err)
 571			}
 572			pc += num - 1
 573			if tableIndex != 0 {
 574				if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
 575					return fmt.Errorf("table index must be zero but was %d: %w", tableIndex, err)
 576				}
 577			}
 578
 579			if tableIndex >= uint32(len(tables)) {
 580				return fmt.Errorf("unknown table index: %d", tableIndex)
 581			}
 582
 583			table := tables[tableIndex]
 584			if table.Type != RefTypeFuncref {
 585				return fmt.Errorf("table is not funcref type but was %s for %s", RefTypeName(table.Type), OpcodeCallIndirectName)
 586			}
 587
 588			if err = valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 589				return fmt.Errorf("cannot pop the offset in table for %s", OpcodeCallIndirectName)
 590			}
 591			funcType := &m.TypeSection[typeIndex]
 592			for i := 0; i < len(funcType.Params); i++ {
 593				if err = valueTypeStack.popAndVerifyType(funcType.Params[len(funcType.Params)-1-i]); err != nil {
 594					return fmt.Errorf("type mismatch on %s operation input type", OpcodeCallIndirectName)
 595				}
 596			}
 597			for _, exp := range funcType.Results {
 598				valueTypeStack.push(exp)
 599			}
 600		} else if OpcodeI32Eqz <= op && op <= OpcodeI64Extend32S {
 601			switch op {
 602			case OpcodeI32Eqz:
 603				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 604					return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI32EqzName, err)
 605				}
 606				valueTypeStack.push(ValueTypeI32)
 607			case OpcodeI32Eq, OpcodeI32Ne, OpcodeI32LtS,
 608				OpcodeI32LtU, OpcodeI32GtS, OpcodeI32GtU, OpcodeI32LeS,
 609				OpcodeI32LeU, OpcodeI32GeS, OpcodeI32GeU:
 610				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 611					return fmt.Errorf("cannot pop the 1st i32 operand for %s: %v", InstructionName(op), err)
 612				}
 613				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 614					return fmt.Errorf("cannot pop the 2nd i32 operand for %s: %v", InstructionName(op), err)
 615				}
 616				valueTypeStack.push(ValueTypeI32)
 617			case OpcodeI64Eqz:
 618				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
 619					return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI64EqzName, err)
 620				}
 621				valueTypeStack.push(ValueTypeI32)
 622			case OpcodeI64Eq, OpcodeI64Ne, OpcodeI64LtS,
 623				OpcodeI64LtU, OpcodeI64GtS, OpcodeI64GtU,
 624				OpcodeI64LeS, OpcodeI64LeU, OpcodeI64GeS, OpcodeI64GeU:
 625				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
 626					return fmt.Errorf("cannot pop the 1st i64 operand for %s: %v", InstructionName(op), err)
 627				}
 628				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
 629					return fmt.Errorf("cannot pop the 2nd i64 operand for %s: %v", InstructionName(op), err)
 630				}
 631				valueTypeStack.push(ValueTypeI32)
 632			case OpcodeF32Eq, OpcodeF32Ne, OpcodeF32Lt, OpcodeF32Gt, OpcodeF32Le, OpcodeF32Ge:
 633				if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
 634					return fmt.Errorf("cannot pop the 1st f32 operand for %s: %v", InstructionName(op), err)
 635				}
 636				if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
 637					return fmt.Errorf("cannot pop the 2nd f32 operand for %s: %v", InstructionName(op), err)
 638				}
 639				valueTypeStack.push(ValueTypeI32)
 640			case OpcodeF64Eq, OpcodeF64Ne, OpcodeF64Lt, OpcodeF64Gt, OpcodeF64Le, OpcodeF64Ge:
 641				if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
 642					return fmt.Errorf("cannot pop the 1st f64 operand for %s: %v", InstructionName(op), err)
 643				}
 644				if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
 645					return fmt.Errorf("cannot pop the 2nd f64 operand for %s: %v", InstructionName(op), err)
 646				}
 647				valueTypeStack.push(ValueTypeI32)
 648			case OpcodeI32Clz, OpcodeI32Ctz, OpcodeI32Popcnt:
 649				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 650					return fmt.Errorf("cannot pop the i32 operand for %s: %v", InstructionName(op), err)
 651				}
 652				valueTypeStack.push(ValueTypeI32)
 653			case OpcodeI32Add, OpcodeI32Sub, OpcodeI32Mul, OpcodeI32DivS,
 654				OpcodeI32DivU, OpcodeI32RemS, OpcodeI32RemU, OpcodeI32And,
 655				OpcodeI32Or, OpcodeI32Xor, OpcodeI32Shl, OpcodeI32ShrS,
 656				OpcodeI32ShrU, OpcodeI32Rotl, OpcodeI32Rotr:
 657				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 658					return fmt.Errorf("cannot pop the 1st operand for %s: %v", InstructionName(op), err)
 659				}
 660				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 661					return fmt.Errorf("cannot pop the 2nd operand for %s: %v", InstructionName(op), err)
 662				}
 663				valueTypeStack.push(ValueTypeI32)
 664			case OpcodeI64Clz, OpcodeI64Ctz, OpcodeI64Popcnt:
 665				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
 666					return fmt.Errorf("cannot pop the i64 operand for %s: %v", InstructionName(op), err)
 667				}
 668				valueTypeStack.push(ValueTypeI64)
 669			case OpcodeI64Add, OpcodeI64Sub, OpcodeI64Mul, OpcodeI64DivS,
 670				OpcodeI64DivU, OpcodeI64RemS, OpcodeI64RemU, OpcodeI64And,
 671				OpcodeI64Or, OpcodeI64Xor, OpcodeI64Shl, OpcodeI64ShrS,
 672				OpcodeI64ShrU, OpcodeI64Rotl, OpcodeI64Rotr:
 673				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
 674					return fmt.Errorf("cannot pop the 1st i64 operand for %s: %v", InstructionName(op), err)
 675				}
 676				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
 677					return fmt.Errorf("cannot pop the 2nd i64 operand for %s: %v", InstructionName(op), err)
 678				}
 679				valueTypeStack.push(ValueTypeI64)
 680			case OpcodeF32Abs, OpcodeF32Neg, OpcodeF32Ceil,
 681				OpcodeF32Floor, OpcodeF32Trunc, OpcodeF32Nearest,
 682				OpcodeF32Sqrt:
 683				if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
 684					return fmt.Errorf("cannot pop the 1st f32 operand for %s: %v", InstructionName(op), err)
 685				}
 686				valueTypeStack.push(ValueTypeF32)
 687			case OpcodeF32Add, OpcodeF32Sub, OpcodeF32Mul,
 688				OpcodeF32Div, OpcodeF32Min, OpcodeF32Max,
 689				OpcodeF32Copysign:
 690				if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
 691					return fmt.Errorf("cannot pop the 1st f32 operand for %s: %v", InstructionName(op), err)
 692				}
 693				if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
 694					return fmt.Errorf("cannot pop the 2nd f32 operand for %s: %v", InstructionName(op), err)
 695				}
 696				valueTypeStack.push(ValueTypeF32)
 697			case OpcodeF64Abs, OpcodeF64Neg, OpcodeF64Ceil,
 698				OpcodeF64Floor, OpcodeF64Trunc, OpcodeF64Nearest,
 699				OpcodeF64Sqrt:
 700				if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
 701					return fmt.Errorf("cannot pop the 1st f64 operand for %s: %v", InstructionName(op), err)
 702				}
 703				valueTypeStack.push(ValueTypeF64)
 704			case OpcodeF64Add, OpcodeF64Sub, OpcodeF64Mul,
 705				OpcodeF64Div, OpcodeF64Min, OpcodeF64Max,
 706				OpcodeF64Copysign:
 707				if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
 708					return fmt.Errorf("cannot pop the 1st f64 operand for %s: %v", InstructionName(op), err)
 709				}
 710				if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
 711					return fmt.Errorf("cannot pop the 2nd f64 operand for %s: %v", InstructionName(op), err)
 712				}
 713				valueTypeStack.push(ValueTypeF64)
 714			case OpcodeI32WrapI64:
 715				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
 716					return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI32WrapI64Name, err)
 717				}
 718				valueTypeStack.push(ValueTypeI32)
 719			case OpcodeI32TruncF32S, OpcodeI32TruncF32U:
 720				if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
 721					return fmt.Errorf("cannot pop the f32 operand for %s: %v", InstructionName(op), err)
 722				}
 723				valueTypeStack.push(ValueTypeI32)
 724			case OpcodeI32TruncF64S, OpcodeI32TruncF64U:
 725				if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
 726					return fmt.Errorf("cannot pop the f64 operand for %s: %v", InstructionName(op), err)
 727				}
 728				valueTypeStack.push(ValueTypeI32)
 729			case OpcodeI64ExtendI32S, OpcodeI64ExtendI32U:
 730				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 731					return fmt.Errorf("cannot pop the i32 operand for %s: %v", InstructionName(op), err)
 732				}
 733				valueTypeStack.push(ValueTypeI64)
 734			case OpcodeI64TruncF32S, OpcodeI64TruncF32U:
 735				if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
 736					return fmt.Errorf("cannot pop the f32 operand for %s: %v", InstructionName(op), err)
 737				}
 738				valueTypeStack.push(ValueTypeI64)
 739			case OpcodeI64TruncF64S, OpcodeI64TruncF64U:
 740				if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
 741					return fmt.Errorf("cannot pop the f64 operand for %s: %v", InstructionName(op), err)
 742				}
 743				valueTypeStack.push(ValueTypeI64)
 744			case OpcodeF32ConvertI32S, OpcodeF32ConvertI32U:
 745				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 746					return fmt.Errorf("cannot pop the i32 operand for %s: %v", InstructionName(op), err)
 747				}
 748				valueTypeStack.push(ValueTypeF32)
 749			case OpcodeF32ConvertI64S, OpcodeF32ConvertI64U:
 750				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
 751					return fmt.Errorf("cannot pop the i64 operand for %s: %v", InstructionName(op), err)
 752				}
 753				valueTypeStack.push(ValueTypeF32)
 754			case OpcodeF32DemoteF64:
 755				if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
 756					return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeF32DemoteF64Name, err)
 757				}
 758				valueTypeStack.push(ValueTypeF32)
 759			case OpcodeF64ConvertI32S, OpcodeF64ConvertI32U:
 760				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 761					return fmt.Errorf("cannot pop the i32 operand for %s: %v", InstructionName(op), err)
 762				}
 763				valueTypeStack.push(ValueTypeF64)
 764			case OpcodeF64ConvertI64S, OpcodeF64ConvertI64U:
 765				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
 766					return fmt.Errorf("cannot pop the i64 operand for %s: %v", InstructionName(op), err)
 767				}
 768				valueTypeStack.push(ValueTypeF64)
 769			case OpcodeF64PromoteF32:
 770				if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
 771					return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeF64PromoteF32Name, err)
 772				}
 773				valueTypeStack.push(ValueTypeF64)
 774			case OpcodeI32ReinterpretF32:
 775				if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
 776					return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI32ReinterpretF32Name, err)
 777				}
 778				valueTypeStack.push(ValueTypeI32)
 779			case OpcodeI64ReinterpretF64:
 780				if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
 781					return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI64ReinterpretF64Name, err)
 782				}
 783				valueTypeStack.push(ValueTypeI64)
 784			case OpcodeF32ReinterpretI32:
 785				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 786					return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeF32ReinterpretI32Name, err)
 787				}
 788				valueTypeStack.push(ValueTypeF32)
 789			case OpcodeF64ReinterpretI64:
 790				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
 791					return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeF64ReinterpretI64Name, err)
 792				}
 793				valueTypeStack.push(ValueTypeF64)
 794			case OpcodeI32Extend8S, OpcodeI32Extend16S:
 795				if err := enabledFeatures.RequireEnabled(api.CoreFeatureSignExtensionOps); err != nil {
 796					return fmt.Errorf("%s invalid as %v", instructionNames[op], err)
 797				}
 798				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
 799					return fmt.Errorf("cannot pop the operand for %s: %v", instructionNames[op], err)
 800				}
 801				valueTypeStack.push(ValueTypeI32)
 802			case OpcodeI64Extend8S, OpcodeI64Extend16S, OpcodeI64Extend32S:
 803				if err := enabledFeatures.RequireEnabled(api.CoreFeatureSignExtensionOps); err != nil {
 804					return fmt.Errorf("%s invalid as %v", instructionNames[op], err)
 805				}
 806				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
 807					return fmt.Errorf("cannot pop the operand for %s: %v", instructionNames[op], err)
 808				}
 809				valueTypeStack.push(ValueTypeI64)
 810			default:
 811				return fmt.Errorf("invalid numeric instruction 0x%x", op)
 812			}
 813		} else if op >= OpcodeRefNull && op <= OpcodeRefFunc {
 814			if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
 815				return fmt.Errorf("%s invalid as %v", instructionNames[op], err)
 816			}
 817			switch op {
 818			case OpcodeRefNull:
 819				pc++
 820				switch reftype := body[pc]; reftype {
 821				case ValueTypeExternref:
 822					valueTypeStack.push(ValueTypeExternref)
 823				case ValueTypeFuncref:
 824					valueTypeStack.push(ValueTypeFuncref)
 825				default:
 826					return fmt.Errorf("unknown type for ref.null: 0x%x", reftype)
 827				}
 828			case OpcodeRefIsNull:
 829				tp, err := valueTypeStack.pop()
 830				if err != nil {
 831					return fmt.Errorf("cannot pop the operand for ref.is_null: %v", err)
 832				} else if !isReferenceValueType(tp) && tp != valueTypeUnknown {
 833					return fmt.Errorf("type mismatch: expected reference type but was %s", ValueTypeName(tp))
 834				}
 835				valueTypeStack.push(ValueTypeI32)
 836			case OpcodeRefFunc:
 837				pc++
 838				index, num, err := leb128.LoadUint32(body[pc:])
 839				if err != nil {
 840					return fmt.Errorf("failed to read function index for ref.func: %v", err)
 841				}
 842				if _, ok := declaredFunctionIndexes[index]; !ok {
 843					return fmt.Errorf("undeclared function index %d for ref.func", index)
 844				}
 845				pc += num - 1
 846				valueTypeStack.push(ValueTypeFuncref)
 847			}
 848		} else if op == OpcodeTableGet || op == OpcodeTableSet {
 849			if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
 850				return fmt.Errorf("%s is invalid as %v", InstructionName(op), err)
 851			}
 852			pc++
 853			tableIndex, num, err := leb128.LoadUint32(body[pc:])
 854			if err != nil {
 855				return fmt.Errorf("read immediate: %v", err)
 856			}
 857			if tableIndex >= uint32(len(tables)) {
 858				return fmt.Errorf("table of index %d not found", tableIndex)
 859			}
 860
 861			refType := tables[tableIndex].Type
 862			if op == OpcodeTableGet {
 863				if err := valueTypeStack.popAndVerifyType(api.ValueTypeI32); err != nil {
 864					return fmt.Errorf("cannot pop the operand for table.get: %v", err)
 865				}
 866				valueTypeStack.push(refType)
 867			} else {
 868				if err := valueTypeStack.popAndVerifyType(refType); err != nil {
 869					return fmt.Errorf("cannot pop the operand for table.set: %v", err)
 870				}
 871				if err := valueTypeStack.popAndVerifyType(api.ValueTypeI32); err != nil {
 872					return fmt.Errorf("cannot pop the operand for table.set: %v", err)
 873				}
 874			}
 875			pc += num - 1
 876		} else if op == OpcodeMiscPrefix {
 877			pc++
 878			// A misc opcode is encoded as an unsigned variable 32-bit integer.
 879			miscOp32, num, err := leb128.LoadUint32(body[pc:])
 880			if err != nil {
 881				return fmt.Errorf("failed to read misc opcode: %v", err)
 882			}
 883			pc += num - 1
 884			miscOpcode := byte(miscOp32)
 885			// If the misc opcode is beyond byte range, it is highly likely this is an invalid binary, or
 886			// it is due to the new opcode from a new proposal. In the latter case, we have to
 887			// change the alias type of OpcodeMisc (which is currently byte) to uint32.
 888			if uint32(byte(miscOp32)) != miscOp32 {
 889				return fmt.Errorf("invalid misc opcode: %#x", miscOp32)
 890			}
 891			if miscOpcode >= OpcodeMiscI32TruncSatF32S && miscOpcode <= OpcodeMiscI64TruncSatF64U {
 892				if err := enabledFeatures.RequireEnabled(api.CoreFeatureNonTrappingFloatToIntConversion); err != nil {
 893					return fmt.Errorf("%s invalid as %v", miscInstructionNames[miscOpcode], err)
 894				}
 895				var inType, outType ValueType
 896				switch miscOpcode {
 897				case OpcodeMiscI32TruncSatF32S, OpcodeMiscI32TruncSatF32U:
 898					inType, outType = ValueTypeF32, ValueTypeI32
 899				case OpcodeMiscI32TruncSatF64S, OpcodeMiscI32TruncSatF64U:
 900					inType, outType = ValueTypeF64, ValueTypeI32
 901				case OpcodeMiscI64TruncSatF32S, OpcodeMiscI64TruncSatF32U:
 902					inType, outType = ValueTypeF32, ValueTypeI64
 903				case OpcodeMiscI64TruncSatF64S, OpcodeMiscI64TruncSatF64U:
 904					inType, outType = ValueTypeF64, ValueTypeI64
 905				}
 906				if err := valueTypeStack.popAndVerifyType(inType); err != nil {
 907					return fmt.Errorf("cannot pop the operand for %s: %v", miscInstructionNames[miscOpcode], err)
 908				}
 909				valueTypeStack.push(outType)
 910			} else if miscOpcode >= OpcodeMiscMemoryInit && miscOpcode <= OpcodeMiscTableCopy {
 911				if err := enabledFeatures.RequireEnabled(api.CoreFeatureBulkMemoryOperations); err != nil {
 912					return fmt.Errorf("%s invalid as %v", miscInstructionNames[miscOpcode], err)
 913				}
 914				var params []ValueType
 915				// Handle opcodes added in bulk-memory-operations/WebAssembly 2.0.
 916				switch miscOpcode {
 917				case OpcodeMiscDataDrop:
 918					if m.DataCountSection == nil {
 919						return fmt.Errorf("%s requires data count section", MiscInstructionName(miscOpcode))
 920					}
 921
 922					// We need to read the index to the data section.
 923					pc++
 924					index, num, err := leb128.LoadUint32(body[pc:])
 925					if err != nil {
 926						return fmt.Errorf("failed to read data segment index for %s: %v", MiscInstructionName(miscOpcode), err)
 927					}
 928					if int(index) >= len(m.DataSection) {
 929						return fmt.Errorf("index %d out of range of data section(len=%d)", index, len(m.DataSection))
 930					}
 931					pc += num - 1
 932				case OpcodeMiscMemoryInit, OpcodeMiscMemoryCopy, OpcodeMiscMemoryFill:
 933					if memory == nil {
 934						return fmt.Errorf("memory must exist for %s", MiscInstructionName(miscOpcode))
 935					}
 936					params = []ValueType{ValueTypeI32, ValueTypeI32, ValueTypeI32}
 937
 938					if miscOpcode == OpcodeMiscMemoryInit {
 939						if m.DataCountSection == nil {
 940							return fmt.Errorf("%s requires data count section", MiscInstructionName(miscOpcode))
 941						}
 942
 943						// We need to read the index to the data section.
 944						pc++
 945						index, num, err := leb128.LoadUint32(body[pc:])
 946						if err != nil {
 947							return fmt.Errorf("failed to read data segment index for %s: %v", MiscInstructionName(miscOpcode), err)
 948						}
 949						if int(index) >= len(m.DataSection) {
 950							return fmt.Errorf("index %d out of range of data section(len=%d)", index, len(m.DataSection))
 951						}
 952						pc += num - 1
 953					}
 954
 955					pc++
 956					val, num, err := leb128.LoadUint32(body[pc:])
 957					if err != nil {
 958						return fmt.Errorf("failed to read memory index for %s: %v", MiscInstructionName(miscOpcode), err)
 959					}
 960					if val != 0 || num != 1 {
 961						return fmt.Errorf("%s reserved byte must be zero encoded with 1 byte", MiscInstructionName(miscOpcode))
 962					}
 963					if miscOpcode == OpcodeMiscMemoryCopy {
 964						pc++
 965						// memory.copy needs two memory index which are reserved as zero.
 966						val, num, err := leb128.LoadUint32(body[pc:])
 967						if err != nil {
 968							return fmt.Errorf("failed to read memory index for %s: %v", MiscInstructionName(miscOpcode), err)
 969						}
 970						if val != 0 || num != 1 {
 971							return fmt.Errorf("%s reserved byte must be zero encoded with 1 byte", MiscInstructionName(miscOpcode))
 972						}
 973					}
 974
 975				case OpcodeMiscTableInit:
 976					params = []ValueType{ValueTypeI32, ValueTypeI32, ValueTypeI32}
 977					pc++
 978					elementIndex, num, err := leb128.LoadUint32(body[pc:])
 979					if err != nil {
 980						return fmt.Errorf("failed to read element segment index for %s: %v", MiscInstructionName(miscOpcode), err)
 981					}
 982					if int(elementIndex) >= len(m.ElementSection) {
 983						return fmt.Errorf("index %d out of range of element section(len=%d)", elementIndex, len(m.ElementSection))
 984					}
 985					pc += num
 986
 987					tableIndex, num, err := leb128.LoadUint32(body[pc:])
 988					if err != nil {
 989						return fmt.Errorf("failed to read source table index for %s: %v", MiscInstructionName(miscOpcode), err)
 990					}
 991					if tableIndex != 0 {
 992						if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
 993							return fmt.Errorf("source table index must be zero for %s as %v", MiscInstructionName(miscOpcode), err)
 994						}
 995					}
 996					if tableIndex >= uint32(len(tables)) {
 997						return fmt.Errorf("table of index %d not found", tableIndex)
 998					}
 999
1000					if m.ElementSection[elementIndex].Type != tables[tableIndex].Type {
1001						return fmt.Errorf("type mismatch for table.init: element type %s does not match table type %s",
1002							RefTypeName(m.ElementSection[elementIndex].Type),
1003							RefTypeName(tables[tableIndex].Type),
1004						)
1005					}
1006					pc += num - 1
1007				case OpcodeMiscElemDrop:
1008					pc++
1009					elementIndex, num, err := leb128.LoadUint32(body[pc:])
1010					if err != nil {
1011						return fmt.Errorf("failed to read element segment index for %s: %v", MiscInstructionName(miscOpcode), err)
1012					} else if int(elementIndex) >= len(m.ElementSection) {
1013						return fmt.Errorf("index %d out of range of element section(len=%d)", elementIndex, len(m.ElementSection))
1014					}
1015					pc += num - 1
1016				case OpcodeMiscTableCopy:
1017					params = []ValueType{ValueTypeI32, ValueTypeI32, ValueTypeI32}
1018					pc++
1019
1020					dstTableIndex, num, err := leb128.LoadUint32(body[pc:])
1021					if err != nil {
1022						return fmt.Errorf("failed to read destination table index for %s: %v", MiscInstructionName(miscOpcode), err)
1023					}
1024					if dstTableIndex != 0 {
1025						if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
1026							return fmt.Errorf("destination table index must be zero for %s as %v", MiscInstructionName(miscOpcode), err)
1027						}
1028					}
1029					if dstTableIndex >= uint32(len(tables)) {
1030						return fmt.Errorf("table of index %d not found", dstTableIndex)
1031					}
1032					pc += num
1033
1034					srcTableIndex, num, err := leb128.LoadUint32(body[pc:])
1035					if err != nil {
1036						return fmt.Errorf("failed to read source table index for %s: %v", MiscInstructionName(miscOpcode), err)
1037					}
1038					if srcTableIndex != 0 {
1039						if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
1040							return fmt.Errorf("source table index must be zero for %s as %v", MiscInstructionName(miscOpcode), err)
1041						}
1042					}
1043					if srcTableIndex >= uint32(len(tables)) {
1044						return fmt.Errorf("table of index %d not found", srcTableIndex)
1045					}
1046
1047					if tables[srcTableIndex].Type != tables[dstTableIndex].Type {
1048						return fmt.Errorf("table type mismatch for table.copy: %s (src) != %s (dst)",
1049							RefTypeName(tables[srcTableIndex].Type), RefTypeName(tables[dstTableIndex].Type))
1050					}
1051
1052					pc += num - 1
1053				}
1054				for _, p := range params {
1055					if err := valueTypeStack.popAndVerifyType(p); err != nil {
1056						return fmt.Errorf("cannot pop the operand for %s: %v", miscInstructionNames[miscOpcode], err)
1057					}
1058				}
1059			} else if miscOpcode >= OpcodeMiscTableGrow && miscOpcode <= OpcodeMiscTableFill {
1060				if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
1061					return fmt.Errorf("%s invalid as %v", miscInstructionNames[miscOpcode], err)
1062				}
1063
1064				pc++
1065				tableIndex, num, err := leb128.LoadUint32(body[pc:])
1066				if err != nil {
1067					return fmt.Errorf("failed to read table index for %s: %v", MiscInstructionName(miscOpcode), err)
1068				}
1069				if tableIndex >= uint32(len(tables)) {
1070					return fmt.Errorf("table of index %d not found", tableIndex)
1071				}
1072				pc += num - 1
1073
1074				var params, results []ValueType
1075				reftype := tables[tableIndex].Type
1076				if miscOpcode == OpcodeMiscTableGrow {
1077					params = []ValueType{ValueTypeI32, reftype}
1078					results = []ValueType{ValueTypeI32}
1079				} else if miscOpcode == OpcodeMiscTableSize {
1080					results = []ValueType{ValueTypeI32}
1081				} else if miscOpcode == OpcodeMiscTableFill {
1082					params = []ValueType{ValueTypeI32, reftype, ValueTypeI32}
1083				}
1084
1085				for _, p := range params {
1086					if err := valueTypeStack.popAndVerifyType(p); err != nil {
1087						return fmt.Errorf("cannot pop the operand for %s: %v", miscInstructionNames[miscOpcode], err)
1088					}
1089				}
1090				for _, r := range results {
1091					valueTypeStack.push(r)
1092				}
1093			} else {
1094				return fmt.Errorf("unknown misc opcode %#x", miscOpcode)
1095			}
1096		} else if op == OpcodeVecPrefix {
1097			pc++
1098			// Vector instructions come with two bytes where the first byte is always OpcodeVecPrefix,
1099			// and the second byte determines the actual instruction.
1100			vecOpcode := body[pc]
1101			if err := enabledFeatures.RequireEnabled(api.CoreFeatureSIMD); err != nil {
1102				return fmt.Errorf("%s invalid as %v", vectorInstructionName[vecOpcode], err)
1103			}
1104
1105			switch vecOpcode {
1106			case OpcodeVecV128Const:
1107				// Read 128-bit = 16 bytes constants
1108				if int(pc+16) >= len(body) {
1109					return fmt.Errorf("cannot read constant vector value for %s", vectorInstructionName[vecOpcode])
1110				}
1111				pc += 16
1112				valueTypeStack.push(ValueTypeV128)
1113			case OpcodeVecV128AnyTrue, OpcodeVecI8x16AllTrue, OpcodeVecI16x8AllTrue, OpcodeVecI32x4AllTrue, OpcodeVecI64x2AllTrue,
1114				OpcodeVecI8x16BitMask, OpcodeVecI16x8BitMask, OpcodeVecI32x4BitMask, OpcodeVecI64x2BitMask:
1115				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1116					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1117				}
1118				valueTypeStack.push(ValueTypeI32)
1119			case OpcodeVecV128Load, OpcodeVecV128Load8x8s, OpcodeVecV128Load8x8u, OpcodeVecV128Load16x4s, OpcodeVecV128Load16x4u,
1120				OpcodeVecV128Load32x2s, OpcodeVecV128Load32x2u, OpcodeVecV128Load8Splat, OpcodeVecV128Load16Splat,
1121				OpcodeVecV128Load32Splat, OpcodeVecV128Load64Splat,
1122				OpcodeVecV128Load32zero, OpcodeVecV128Load64zero:
1123				if memory == nil {
1124					return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode))
1125				}
1126				pc++
1127				align, _, read, err := readMemArg(pc, body)
1128				if err != nil {
1129					return err
1130				}
1131				pc += read - 1
1132				var maxAlign uint32
1133				switch vecOpcode {
1134				case OpcodeVecV128Load:
1135					maxAlign = 128 / 8
1136				case OpcodeVecV128Load8x8s, OpcodeVecV128Load8x8u, OpcodeVecV128Load16x4s, OpcodeVecV128Load16x4u,
1137					OpcodeVecV128Load32x2s, OpcodeVecV128Load32x2u:
1138					maxAlign = 64 / 8
1139				case OpcodeVecV128Load8Splat:
1140					maxAlign = 1
1141				case OpcodeVecV128Load16Splat:
1142					maxAlign = 16 / 8
1143				case OpcodeVecV128Load32Splat:
1144					maxAlign = 32 / 8
1145				case OpcodeVecV128Load64Splat:
1146					maxAlign = 64 / 8
1147				case OpcodeVecV128Load32zero:
1148					maxAlign = 32 / 8
1149				case OpcodeVecV128Load64zero:
1150					maxAlign = 64 / 8
1151				}
1152
1153				if 1<<align > maxAlign {
1154					return fmt.Errorf("invalid memory alignment %d for %s", align, VectorInstructionName(vecOpcode))
1155				}
1156				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1157					return fmt.Errorf("cannot pop the operand for %s: %v", VectorInstructionName(vecOpcode), err)
1158				}
1159				valueTypeStack.push(ValueTypeV128)
1160			case OpcodeVecV128Store:
1161				if memory == nil {
1162					return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode))
1163				}
1164				pc++
1165				align, _, read, err := readMemArg(pc, body)
1166				if err != nil {
1167					return err
1168				}
1169				pc += read - 1
1170				if 1<<align > 128/8 {
1171					return fmt.Errorf("invalid memory alignment %d for %s", align, OpcodeVecV128StoreName)
1172				}
1173				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1174					return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeVecV128StoreName, err)
1175				}
1176				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1177					return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeVecV128StoreName, err)
1178				}
1179			case OpcodeVecV128Load8Lane, OpcodeVecV128Load16Lane, OpcodeVecV128Load32Lane, OpcodeVecV128Load64Lane:
1180				if memory == nil {
1181					return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode))
1182				}
1183				attr := vecLoadLanes[vecOpcode]
1184				pc++
1185				align, _, read, err := readMemArg(pc, body)
1186				if err != nil {
1187					return err
1188				}
1189				if 1<<align > attr.alignMax {
1190					return fmt.Errorf("invalid memory alignment %d for %s", align, vectorInstructionName[vecOpcode])
1191				}
1192				pc += read
1193				if pc >= uint64(len(body)) {
1194					return fmt.Errorf("lane for %s not found", OpcodeVecV128Load64LaneName)
1195				}
1196				lane := body[pc]
1197				if lane >= attr.laneCeil {
1198					return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode])
1199				}
1200				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1201					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1202				}
1203				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1204					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1205				}
1206				valueTypeStack.push(ValueTypeV128)
1207			case OpcodeVecV128Store8Lane, OpcodeVecV128Store16Lane, OpcodeVecV128Store32Lane, OpcodeVecV128Store64Lane:
1208				if memory == nil {
1209					return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode))
1210				}
1211				attr := vecStoreLanes[vecOpcode]
1212				pc++
1213				align, _, read, err := readMemArg(pc, body)
1214				if err != nil {
1215					return err
1216				}
1217				if 1<<align > attr.alignMax {
1218					return fmt.Errorf("invalid memory alignment %d for %s", align, vectorInstructionName[vecOpcode])
1219				}
1220				pc += read
1221				if pc >= uint64(len(body)) {
1222					return fmt.Errorf("lane for %s not found", vectorInstructionName[vecOpcode])
1223				}
1224				lane := body[pc]
1225				if lane >= attr.laneCeil {
1226					return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode])
1227				}
1228				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1229					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1230				}
1231				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1232					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1233				}
1234			case OpcodeVecI8x16ExtractLaneS,
1235				OpcodeVecI8x16ExtractLaneU,
1236				OpcodeVecI16x8ExtractLaneS,
1237				OpcodeVecI16x8ExtractLaneU,
1238				OpcodeVecI32x4ExtractLane,
1239				OpcodeVecI64x2ExtractLane,
1240				OpcodeVecF32x4ExtractLane,
1241				OpcodeVecF64x2ExtractLane:
1242				pc++
1243				if pc >= uint64(len(body)) {
1244					return fmt.Errorf("lane for %s not found", vectorInstructionName[vecOpcode])
1245				}
1246				attr := vecExtractLanes[vecOpcode]
1247				lane := body[pc]
1248				if lane >= attr.laneCeil {
1249					return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode])
1250				}
1251				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1252					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1253				}
1254				valueTypeStack.push(attr.resultType)
1255			case OpcodeVecI8x16ReplaceLane, OpcodeVecI16x8ReplaceLane, OpcodeVecI32x4ReplaceLane,
1256				OpcodeVecI64x2ReplaceLane, OpcodeVecF32x4ReplaceLane, OpcodeVecF64x2ReplaceLane:
1257				pc++
1258				if pc >= uint64(len(body)) {
1259					return fmt.Errorf("lane for %s not found", vectorInstructionName[vecOpcode])
1260				}
1261				attr := vecReplaceLanes[vecOpcode]
1262				lane := body[pc]
1263				if lane >= attr.laneCeil {
1264					return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode])
1265				}
1266				if err := valueTypeStack.popAndVerifyType(attr.paramType); err != nil {
1267					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1268				}
1269				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1270					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1271				}
1272				valueTypeStack.push(ValueTypeV128)
1273			case OpcodeVecI8x16Splat, OpcodeVecI16x8Splat, OpcodeVecI32x4Splat,
1274				OpcodeVecI64x2Splat, OpcodeVecF32x4Splat, OpcodeVecF64x2Splat:
1275				tp := vecSplatValueTypes[vecOpcode]
1276				if err := valueTypeStack.popAndVerifyType(tp); err != nil {
1277					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1278				}
1279				valueTypeStack.push(ValueTypeV128)
1280			case OpcodeVecI8x16Swizzle, OpcodeVecV128And, OpcodeVecV128Or, OpcodeVecV128Xor, OpcodeVecV128AndNot:
1281				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1282					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1283				}
1284				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1285					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1286				}
1287				valueTypeStack.push(ValueTypeV128)
1288			case OpcodeVecV128Bitselect:
1289				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1290					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1291				}
1292				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1293					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1294				}
1295				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1296					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1297				}
1298				valueTypeStack.push(ValueTypeV128)
1299			case OpcodeVecV128Not:
1300				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1301					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1302				}
1303				valueTypeStack.push(ValueTypeV128)
1304			case OpcodeVecV128i8x16Shuffle:
1305				pc++
1306				if pc+15 >= uint64(len(body)) {
1307					return fmt.Errorf("16 lane indexes for %s not found", vectorInstructionName[vecOpcode])
1308				}
1309				lanes := body[pc : pc+16]
1310				for i, l := range lanes {
1311					if l >= 32 {
1312						return fmt.Errorf("invalid lane index[%d] %d >= %d for %s", i, l, 32, vectorInstructionName[vecOpcode])
1313					}
1314				}
1315				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1316					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1317				}
1318				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1319					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1320				}
1321				valueTypeStack.push(ValueTypeV128)
1322				pc += 15
1323			case OpcodeVecI8x16Shl, OpcodeVecI8x16ShrS, OpcodeVecI8x16ShrU,
1324				OpcodeVecI16x8Shl, OpcodeVecI16x8ShrS, OpcodeVecI16x8ShrU,
1325				OpcodeVecI32x4Shl, OpcodeVecI32x4ShrS, OpcodeVecI32x4ShrU,
1326				OpcodeVecI64x2Shl, OpcodeVecI64x2ShrS, OpcodeVecI64x2ShrU:
1327				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1328					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1329				}
1330				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1331					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1332				}
1333				valueTypeStack.push(ValueTypeV128)
1334			case OpcodeVecI8x16Eq, OpcodeVecI8x16Ne, OpcodeVecI8x16LtS, OpcodeVecI8x16LtU, OpcodeVecI8x16GtS,
1335				OpcodeVecI8x16GtU, OpcodeVecI8x16LeS, OpcodeVecI8x16LeU, OpcodeVecI8x16GeS, OpcodeVecI8x16GeU,
1336				OpcodeVecI16x8Eq, OpcodeVecI16x8Ne, OpcodeVecI16x8LtS, OpcodeVecI16x8LtU, OpcodeVecI16x8GtS,
1337				OpcodeVecI16x8GtU, OpcodeVecI16x8LeS, OpcodeVecI16x8LeU, OpcodeVecI16x8GeS, OpcodeVecI16x8GeU,
1338				OpcodeVecI32x4Eq, OpcodeVecI32x4Ne, OpcodeVecI32x4LtS, OpcodeVecI32x4LtU, OpcodeVecI32x4GtS,
1339				OpcodeVecI32x4GtU, OpcodeVecI32x4LeS, OpcodeVecI32x4LeU, OpcodeVecI32x4GeS, OpcodeVecI32x4GeU,
1340				OpcodeVecI64x2Eq, OpcodeVecI64x2Ne, OpcodeVecI64x2LtS, OpcodeVecI64x2GtS, OpcodeVecI64x2LeS,
1341				OpcodeVecI64x2GeS, OpcodeVecF32x4Eq, OpcodeVecF32x4Ne, OpcodeVecF32x4Lt, OpcodeVecF32x4Gt,
1342				OpcodeVecF32x4Le, OpcodeVecF32x4Ge, OpcodeVecF64x2Eq, OpcodeVecF64x2Ne, OpcodeVecF64x2Lt,
1343				OpcodeVecF64x2Gt, OpcodeVecF64x2Le, OpcodeVecF64x2Ge,
1344				OpcodeVecI32x4DotI16x8S,
1345				OpcodeVecI8x16NarrowI16x8S, OpcodeVecI8x16NarrowI16x8U, OpcodeVecI16x8NarrowI32x4S, OpcodeVecI16x8NarrowI32x4U:
1346				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1347					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1348				}
1349				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1350					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1351				}
1352				valueTypeStack.push(ValueTypeV128)
1353			case OpcodeVecI8x16Neg, OpcodeVecI16x8Neg, OpcodeVecI32x4Neg, OpcodeVecI64x2Neg, OpcodeVecF32x4Neg, OpcodeVecF64x2Neg,
1354				OpcodeVecF32x4Sqrt, OpcodeVecF64x2Sqrt,
1355				OpcodeVecI8x16Abs, OpcodeVecI8x16Popcnt, OpcodeVecI16x8Abs, OpcodeVecI32x4Abs, OpcodeVecI64x2Abs,
1356				OpcodeVecF32x4Abs, OpcodeVecF64x2Abs,
1357				OpcodeVecF32x4Ceil, OpcodeVecF32x4Floor, OpcodeVecF32x4Trunc, OpcodeVecF32x4Nearest,
1358				OpcodeVecF64x2Ceil, OpcodeVecF64x2Floor, OpcodeVecF64x2Trunc, OpcodeVecF64x2Nearest,
1359				OpcodeVecI16x8ExtendLowI8x16S, OpcodeVecI16x8ExtendHighI8x16S, OpcodeVecI16x8ExtendLowI8x16U, OpcodeVecI16x8ExtendHighI8x16U,
1360				OpcodeVecI32x4ExtendLowI16x8S, OpcodeVecI32x4ExtendHighI16x8S, OpcodeVecI32x4ExtendLowI16x8U, OpcodeVecI32x4ExtendHighI16x8U,
1361				OpcodeVecI64x2ExtendLowI32x4S, OpcodeVecI64x2ExtendHighI32x4S, OpcodeVecI64x2ExtendLowI32x4U, OpcodeVecI64x2ExtendHighI32x4U,
1362				OpcodeVecI16x8ExtaddPairwiseI8x16S, OpcodeVecI16x8ExtaddPairwiseI8x16U,
1363				OpcodeVecI32x4ExtaddPairwiseI16x8S, OpcodeVecI32x4ExtaddPairwiseI16x8U,
1364				OpcodeVecF64x2PromoteLowF32x4Zero, OpcodeVecF32x4DemoteF64x2Zero,
1365				OpcodeVecF32x4ConvertI32x4S, OpcodeVecF32x4ConvertI32x4U,
1366				OpcodeVecF64x2ConvertLowI32x4S, OpcodeVecF64x2ConvertLowI32x4U,
1367				OpcodeVecI32x4TruncSatF32x4S, OpcodeVecI32x4TruncSatF32x4U, OpcodeVecI32x4TruncSatF64x2SZero, OpcodeVecI32x4TruncSatF64x2UZero:
1368				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1369					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1370				}
1371				valueTypeStack.push(ValueTypeV128)
1372
1373			case OpcodeVecI8x16Add, OpcodeVecI8x16AddSatS, OpcodeVecI8x16AddSatU, OpcodeVecI8x16Sub, OpcodeVecI8x16SubSatS, OpcodeVecI8x16SubSatU,
1374				OpcodeVecI16x8Add, OpcodeVecI16x8AddSatS, OpcodeVecI16x8AddSatU, OpcodeVecI16x8Sub, OpcodeVecI16x8SubSatS, OpcodeVecI16x8SubSatU, OpcodeVecI16x8Mul,
1375				OpcodeVecI32x4Add, OpcodeVecI32x4Sub, OpcodeVecI32x4Mul,
1376				OpcodeVecI64x2Add, OpcodeVecI64x2Sub, OpcodeVecI64x2Mul,
1377				OpcodeVecF32x4Add, OpcodeVecF32x4Sub, OpcodeVecF32x4Mul, OpcodeVecF32x4Div,
1378				OpcodeVecF64x2Add, OpcodeVecF64x2Sub, OpcodeVecF64x2Mul, OpcodeVecF64x2Div,
1379				OpcodeVecI8x16MinS, OpcodeVecI8x16MinU, OpcodeVecI8x16MaxS, OpcodeVecI8x16MaxU,
1380				OpcodeVecI8x16AvgrU,
1381				OpcodeVecI16x8MinS, OpcodeVecI16x8MinU, OpcodeVecI16x8MaxS, OpcodeVecI16x8MaxU,
1382				OpcodeVecI16x8AvgrU,
1383				OpcodeVecI32x4MinS, OpcodeVecI32x4MinU, OpcodeVecI32x4MaxS, OpcodeVecI32x4MaxU,
1384				OpcodeVecF32x4Min, OpcodeVecF32x4Max, OpcodeVecF64x2Min, OpcodeVecF64x2Max,
1385				OpcodeVecF32x4Pmin, OpcodeVecF32x4Pmax, OpcodeVecF64x2Pmin, OpcodeVecF64x2Pmax,
1386				OpcodeVecI16x8Q15mulrSatS,
1387				OpcodeVecI16x8ExtMulLowI8x16S, OpcodeVecI16x8ExtMulHighI8x16S, OpcodeVecI16x8ExtMulLowI8x16U, OpcodeVecI16x8ExtMulHighI8x16U,
1388				OpcodeVecI32x4ExtMulLowI16x8S, OpcodeVecI32x4ExtMulHighI16x8S, OpcodeVecI32x4ExtMulLowI16x8U, OpcodeVecI32x4ExtMulHighI16x8U,
1389				OpcodeVecI64x2ExtMulLowI32x4S, OpcodeVecI64x2ExtMulHighI32x4S, OpcodeVecI64x2ExtMulLowI32x4U, OpcodeVecI64x2ExtMulHighI32x4U:
1390				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1391					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1392				}
1393				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1394					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1395				}
1396				valueTypeStack.push(ValueTypeV128)
1397			default:
1398				return fmt.Errorf("unknown SIMD instruction %s", vectorInstructionName[vecOpcode])
1399			}
1400		} else if op == OpcodeBlock {
1401			br.Reset(body[pc+1:])
1402			bt, num, err := DecodeBlockType(m.TypeSection, br, enabledFeatures)
1403			if err != nil {
1404				return fmt.Errorf("read block: %w", err)
1405			}
1406			controlBlockStack.push(pc, 0, 0, bt, num, 0)
1407			if err = valueTypeStack.popParams(op, bt.Params, false); err != nil {
1408				return err
1409			}
1410			// Plus we have to push any block params again.
1411			for _, p := range bt.Params {
1412				valueTypeStack.push(p)
1413			}
1414			valueTypeStack.pushStackLimit(len(bt.Params))
1415			pc += num
1416		} else if op == OpcodeAtomicPrefix {
1417			pc++
1418			// Atomic instructions come with two bytes where the first byte is always OpcodeAtomicPrefix,
1419			// and the second byte determines the actual instruction.
1420			atomicOpcode := body[pc]
1421			if err := enabledFeatures.RequireEnabled(experimental.CoreFeaturesThreads); err != nil {
1422				return fmt.Errorf("%s invalid as %v", atomicInstructionName[atomicOpcode], err)
1423			}
1424			pc++
1425
1426			if atomicOpcode == OpcodeAtomicFence {
1427				// No memory requirement and no arguments or return, however the immediate byte value must be 0.
1428				imm := body[pc]
1429				if imm != 0x0 {
1430					return fmt.Errorf("invalid immediate value for %s", AtomicInstructionName(atomicOpcode))
1431				}
1432				continue
1433			}
1434
1435			// All atomic operations except fence (checked above) require memory
1436			if memory == nil {
1437				return fmt.Errorf("memory must exist for %s", AtomicInstructionName(atomicOpcode))
1438			}
1439			align, _, read, err := readMemArg(pc, body)
1440			if err != nil {
1441				return err
1442			}
1443			pc += read - 1
1444			switch atomicOpcode {
1445			case OpcodeAtomicMemoryNotify:
1446				if 1<<align > 32/8 {
1447					return fmt.Errorf("invalid memory alignment")
1448				}
1449				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1450					return err
1451				}
1452				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1453					return err
1454				}
1455				valueTypeStack.push(ValueTypeI32)
1456			case OpcodeAtomicMemoryWait32:
1457				if 1<<align > 32/8 {
1458					return fmt.Errorf("invalid memory alignment")
1459				}
1460				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1461					return err
1462				}
1463				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1464					return err
1465				}
1466				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1467					return err
1468				}
1469				valueTypeStack.push(ValueTypeI32)
1470			case OpcodeAtomicMemoryWait64:
1471				if 1<<align > 64/8 {
1472					return fmt.Errorf("invalid memory alignment")
1473				}
1474				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1475					return err
1476				}
1477				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1478					return err
1479				}
1480				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1481					return err
1482				}
1483				valueTypeStack.push(ValueTypeI32)
1484			case OpcodeAtomicI32Load:
1485				if 1<<align > 32/8 {
1486					return fmt.Errorf("invalid memory alignment")
1487				}
1488				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1489					return err
1490				}
1491				valueTypeStack.push(ValueTypeI32)
1492			case OpcodeAtomicI64Load:
1493				if 1<<align > 64/8 {
1494					return fmt.Errorf("invalid memory alignment")
1495				}
1496				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1497					return err
1498				}
1499				valueTypeStack.push(ValueTypeI64)
1500			case OpcodeAtomicI32Load8U:
1501				if 1<<align != 1 {
1502					return fmt.Errorf("invalid memory alignment")
1503				}
1504				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1505					return err
1506				}
1507				valueTypeStack.push(ValueTypeI32)
1508			case OpcodeAtomicI32Load16U:
1509				if 1<<align != 16/8 {
1510					return fmt.Errorf("invalid memory alignment")
1511				}
1512				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1513					return err
1514				}
1515				valueTypeStack.push(ValueTypeI32)
1516			case OpcodeAtomicI64Load8U:
1517				if 1<<align != 1 {
1518					return fmt.Errorf("invalid memory alignment")
1519				}
1520				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1521					return err
1522				}
1523				valueTypeStack.push(ValueTypeI64)
1524			case OpcodeAtomicI64Load16U:
1525				if 1<<align > 16/8 {
1526					return fmt.Errorf("invalid memory alignment")
1527				}
1528				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1529					return err
1530				}
1531				valueTypeStack.push(ValueTypeI64)
1532			case OpcodeAtomicI64Load32U:
1533				if 1<<align > 32/8 {
1534					return fmt.Errorf("invalid memory alignment")
1535				}
1536				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1537					return err
1538				}
1539				valueTypeStack.push(ValueTypeI64)
1540			case OpcodeAtomicI32Store:
1541				if 1<<align > 32/8 {
1542					return fmt.Errorf("invalid memory alignment")
1543				}
1544				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1545					return err
1546				}
1547				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1548					return err
1549				}
1550			case OpcodeAtomicI64Store:
1551				if 1<<align > 64/8 {
1552					return fmt.Errorf("invalid memory alignment")
1553				}
1554				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1555					return err
1556				}
1557				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1558					return err
1559				}
1560			case OpcodeAtomicI32Store8:
1561				if 1<<align > 1 {
1562					return fmt.Errorf("invalid memory alignment")
1563				}
1564				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1565					return err
1566				}
1567				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1568					return err
1569				}
1570			case OpcodeAtomicI32Store16:
1571				if 1<<align > 16/8 {
1572					return fmt.Errorf("invalid memory alignment")
1573				}
1574				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1575					return err
1576				}
1577				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1578					return err
1579				}
1580			case OpcodeAtomicI64Store8:
1581				if 1<<align > 1 {
1582					return fmt.Errorf("invalid memory alignment")
1583				}
1584				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1585					return err
1586				}
1587				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1588					return err
1589				}
1590			case OpcodeAtomicI64Store16:
1591				if 1<<align > 16/8 {
1592					return fmt.Errorf("invalid memory alignment")
1593				}
1594				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1595					return err
1596				}
1597				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1598					return err
1599				}
1600			case OpcodeAtomicI64Store32:
1601				if 1<<align > 32/8 {
1602					return fmt.Errorf("invalid memory alignment")
1603				}
1604				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1605					return err
1606				}
1607				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1608					return err
1609				}
1610			case OpcodeAtomicI32RmwAdd, OpcodeAtomicI32RmwSub, OpcodeAtomicI32RmwAnd, OpcodeAtomicI32RmwOr, OpcodeAtomicI32RmwXor, OpcodeAtomicI32RmwXchg:
1611				if 1<<align > 32/8 {
1612					return fmt.Errorf("invalid memory alignment")
1613				}
1614				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1615					return err
1616				}
1617				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1618					return err
1619				}
1620				valueTypeStack.push(ValueTypeI32)
1621			case OpcodeAtomicI32Rmw8AddU, OpcodeAtomicI32Rmw8SubU, OpcodeAtomicI32Rmw8AndU, OpcodeAtomicI32Rmw8OrU, OpcodeAtomicI32Rmw8XorU, OpcodeAtomicI32Rmw8XchgU:
1622				if 1<<align > 1 {
1623					return fmt.Errorf("invalid memory alignment")
1624				}
1625				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1626					return err
1627				}
1628				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1629					return err
1630				}
1631				valueTypeStack.push(ValueTypeI32)
1632			case OpcodeAtomicI32Rmw16AddU, OpcodeAtomicI32Rmw16SubU, OpcodeAtomicI32Rmw16AndU, OpcodeAtomicI32Rmw16OrU, OpcodeAtomicI32Rmw16XorU, OpcodeAtomicI32Rmw16XchgU:
1633				if 1<<align > 16/8 {
1634					return fmt.Errorf("invalid memory alignment")
1635				}
1636				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1637					return err
1638				}
1639				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1640					return err
1641				}
1642				valueTypeStack.push(ValueTypeI32)
1643			case OpcodeAtomicI64RmwAdd, OpcodeAtomicI64RmwSub, OpcodeAtomicI64RmwAnd, OpcodeAtomicI64RmwOr, OpcodeAtomicI64RmwXor, OpcodeAtomicI64RmwXchg:
1644				if 1<<align > 64/8 {
1645					return fmt.Errorf("invalid memory alignment")
1646				}
1647				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1648					return err
1649				}
1650				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1651					return err
1652				}
1653				valueTypeStack.push(ValueTypeI64)
1654			case OpcodeAtomicI64Rmw8AddU, OpcodeAtomicI64Rmw8SubU, OpcodeAtomicI64Rmw8AndU, OpcodeAtomicI64Rmw8OrU, OpcodeAtomicI64Rmw8XorU, OpcodeAtomicI64Rmw8XchgU:
1655				if 1<<align > 1 {
1656					return fmt.Errorf("invalid memory alignment")
1657				}
1658				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1659					return err
1660				}
1661				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1662					return err
1663				}
1664				valueTypeStack.push(ValueTypeI64)
1665			case OpcodeAtomicI64Rmw16AddU, OpcodeAtomicI64Rmw16SubU, OpcodeAtomicI64Rmw16AndU, OpcodeAtomicI64Rmw16OrU, OpcodeAtomicI64Rmw16XorU, OpcodeAtomicI64Rmw16XchgU:
1666				if 1<<align > 16/8 {
1667					return fmt.Errorf("invalid memory alignment")
1668				}
1669				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1670					return err
1671				}
1672				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1673					return err
1674				}
1675				valueTypeStack.push(ValueTypeI64)
1676			case OpcodeAtomicI64Rmw32AddU, OpcodeAtomicI64Rmw32SubU, OpcodeAtomicI64Rmw32AndU, OpcodeAtomicI64Rmw32OrU, OpcodeAtomicI64Rmw32XorU, OpcodeAtomicI64Rmw32XchgU:
1677				if 1<<align > 32/8 {
1678					return fmt.Errorf("invalid memory alignment")
1679				}
1680				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1681					return err
1682				}
1683				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1684					return err
1685				}
1686				valueTypeStack.push(ValueTypeI64)
1687			case OpcodeAtomicI32RmwCmpxchg:
1688				if 1<<align > 32/8 {
1689					return fmt.Errorf("invalid memory alignment")
1690				}
1691				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1692					return err
1693				}
1694				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1695					return err
1696				}
1697				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1698					return err
1699				}
1700				valueTypeStack.push(ValueTypeI32)
1701			case OpcodeAtomicI32Rmw8CmpxchgU:
1702				if 1<<align > 1 {
1703					return fmt.Errorf("invalid memory alignment")
1704				}
1705				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1706					return err
1707				}
1708				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1709					return err
1710				}
1711				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1712					return err
1713				}
1714				valueTypeStack.push(ValueTypeI32)
1715			case OpcodeAtomicI32Rmw16CmpxchgU:
1716				if 1<<align > 16/8 {
1717					return fmt.Errorf("invalid memory alignment")
1718				}
1719				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1720					return err
1721				}
1722				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1723					return err
1724				}
1725				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1726					return err
1727				}
1728				valueTypeStack.push(ValueTypeI32)
1729			case OpcodeAtomicI64RmwCmpxchg:
1730				if 1<<align > 64/8 {
1731					return fmt.Errorf("invalid memory alignment")
1732				}
1733				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1734					return err
1735				}
1736				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1737					return err
1738				}
1739				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1740					return err
1741				}
1742				valueTypeStack.push(ValueTypeI64)
1743			case OpcodeAtomicI64Rmw8CmpxchgU:
1744				if 1<<align > 1 {
1745					return fmt.Errorf("invalid memory alignment")
1746				}
1747				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1748					return err
1749				}
1750				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1751					return err
1752				}
1753				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1754					return err
1755				}
1756				valueTypeStack.push(ValueTypeI64)
1757			case OpcodeAtomicI64Rmw16CmpxchgU:
1758				if 1<<align > 16/8 {
1759					return fmt.Errorf("invalid memory alignment")
1760				}
1761				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1762					return err
1763				}
1764				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1765					return err
1766				}
1767				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1768					return err
1769				}
1770				valueTypeStack.push(ValueTypeI64)
1771			case OpcodeAtomicI64Rmw32CmpxchgU:
1772				if 1<<align > 32/8 {
1773					return fmt.Errorf("invalid memory alignment")
1774				}
1775				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1776					return err
1777				}
1778				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1779					return err
1780				}
1781				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1782					return err
1783				}
1784				valueTypeStack.push(ValueTypeI64)
1785			default:
1786				return fmt.Errorf("invalid atomic opcode: 0x%x", atomicOpcode)
1787			}
1788		} else if op == OpcodeLoop {
1789			br.Reset(body[pc+1:])
1790			bt, num, err := DecodeBlockType(m.TypeSection, br, enabledFeatures)
1791			if err != nil {
1792				return fmt.Errorf("read block: %w", err)
1793			}
1794			controlBlockStack.push(pc, 0, 0, bt, num, op)
1795			if err = valueTypeStack.popParams(op, bt.Params, false); err != nil {
1796				return err
1797			}
1798			// Plus we have to push any block params again.
1799			for _, p := range bt.Params {
1800				valueTypeStack.push(p)
1801			}
1802			valueTypeStack.pushStackLimit(len(bt.Params))
1803			pc += num
1804		} else if op == OpcodeIf {
1805			br.Reset(body[pc+1:])
1806			bt, num, err := DecodeBlockType(m.TypeSection, br, enabledFeatures)
1807			if err != nil {
1808				return fmt.Errorf("read block: %w", err)
1809			}
1810			controlBlockStack.push(pc, 0, 0, bt, num, op)
1811			if err = valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1812				return fmt.Errorf("cannot pop the operand for 'if': %v", err)
1813			}
1814			if err = valueTypeStack.popParams(op, bt.Params, false); err != nil {
1815				return err
1816			}
1817			// Plus we have to push any block params again.
1818			for _, p := range bt.Params {
1819				valueTypeStack.push(p)
1820			}
1821			valueTypeStack.pushStackLimit(len(bt.Params))
1822			pc += num
1823		} else if op == OpcodeElse {
1824			bl := &controlBlockStack.stack[len(controlBlockStack.stack)-1]
1825			if bl.op != OpcodeIf {
1826				return fmt.Errorf("else instruction must be used in if block: %#x", pc)
1827			}
1828			bl.op = OpcodeElse
1829			bl.elseAt = pc
1830			// Check the type soundness of the instructions *before* entering this else Op.
1831			if err := valueTypeStack.popResults(OpcodeIf, bl.blockType.Results, true); err != nil {
1832				return err
1833			}
1834			// Before entering instructions inside else, we pop all the values pushed by then block.
1835			valueTypeStack.resetAtStackLimit()
1836			// Plus we have to push any block params again.
1837			for _, p := range bl.blockType.Params {
1838				valueTypeStack.push(p)
1839			}
1840		} else if op == OpcodeEnd {
1841			bl := controlBlockStack.pop()
1842			bl.endAt = pc
1843
1844			// OpcodeEnd can end a block or the function itself. Check to see what it is:
1845
1846			ifMissingElse := bl.op == OpcodeIf && bl.elseAt <= bl.startAt
1847			if ifMissingElse {
1848				// If this is the end of block without else, the number of block's results and params must be same.
1849				// Otherwise, the value stack would result in the inconsistent state at runtime.
1850				if !bytes.Equal(bl.blockType.Results, bl.blockType.Params) {
1851					return typeCountError(false, OpcodeElseName, bl.blockType.Params, bl.blockType.Results)
1852				}
1853				// -1 skips else, to handle if block without else properly.
1854				bl.elseAt = bl.endAt - 1
1855			}
1856
1857			// Determine the block context
1858			ctx := "" // the outer-most block: the function return
1859			if bl.op == OpcodeIf && !ifMissingElse && bl.elseAt > 0 {
1860				ctx = OpcodeElseName
1861			} else if bl.op != 0 {
1862				ctx = InstructionName(bl.op)
1863			}
1864
1865			// Check return types match
1866			if err := valueTypeStack.requireStackValues(false, ctx, bl.blockType.Results, true); err != nil {
1867				return err
1868			}
1869
1870			// Put the result types at the end after resetting at the stack limit
1871			// since we might have Any type between the limit and the current top.
1872			valueTypeStack.resetAtStackLimit()
1873			for _, exp := range bl.blockType.Results {
1874				valueTypeStack.push(exp)
1875			}
1876			// We exit if/loop/block, so reset the constraints on the stack manipulation
1877			// on values previously pushed by outer blocks.
1878			valueTypeStack.popStackLimit()
1879		} else if op == OpcodeReturn {
1880			// Same formatting as OpcodeEnd on the outer-most block
1881			if err := valueTypeStack.requireStackValues(false, "", functionType.Results, false); err != nil {
1882				return err
1883			}
1884			// return instruction is stack-polymorphic.
1885			valueTypeStack.unreachable()
1886		} else if op == OpcodeDrop {
1887			_, err := valueTypeStack.pop()
1888			if err != nil {
1889				return fmt.Errorf("invalid drop: %v", err)
1890			}
1891		} else if op == OpcodeSelect || op == OpcodeTypedSelect {
1892			if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1893				return fmt.Errorf("type mismatch on 3rd select operand: %v", err)
1894			}
1895			v1, err := valueTypeStack.pop()
1896			if err != nil {
1897				return fmt.Errorf("invalid select: %v", err)
1898			}
1899			v2, err := valueTypeStack.pop()
1900			if err != nil {
1901				return fmt.Errorf("invalid select: %v", err)
1902			}
1903
1904			if op == OpcodeTypedSelect {
1905				if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
1906					return fmt.Errorf("%s is invalid as %w", InstructionName(op), err)
1907				}
1908				pc++
1909				if numTypeImmeidates := body[pc]; numTypeImmeidates != 1 {
1910					return fmt.Errorf("too many type immediates for %s", InstructionName(op))
1911				}
1912				pc++
1913				tp := body[pc]
1914				if tp != ValueTypeI32 && tp != ValueTypeI64 && tp != ValueTypeF32 && tp != ValueTypeF64 &&
1915					tp != api.ValueTypeExternref && tp != ValueTypeFuncref && tp != ValueTypeV128 {
1916					return fmt.Errorf("invalid type %s for %s", ValueTypeName(tp), OpcodeTypedSelectName)
1917				}
1918			} else if isReferenceValueType(v1) || isReferenceValueType(v2) {
1919				return fmt.Errorf("reference types cannot be used for non typed select instruction")
1920			}
1921
1922			if v1 != v2 && v1 != valueTypeUnknown && v2 != valueTypeUnknown {
1923				return fmt.Errorf("type mismatch on 1st and 2nd select operands")
1924			}
1925			if v1 == valueTypeUnknown {
1926				valueTypeStack.push(v2)
1927			} else {
1928				valueTypeStack.push(v1)
1929			}
1930		} else if op == OpcodeUnreachable {
1931			// unreachable instruction is stack-polymorphic.
1932			valueTypeStack.unreachable()
1933		} else if op == OpcodeNop {
1934		} else {
1935			return fmt.Errorf("invalid instruction 0x%x", op)
1936		}
1937	}
1938
1939	if len(controlBlockStack.stack) > 0 {
1940		return fmt.Errorf("ill-nested block exists")
1941	}
1942	if valueTypeStack.maximumStackPointer > maxStackValues {
1943		return fmt.Errorf("function may have %d stack values, which exceeds limit %d", valueTypeStack.maximumStackPointer, maxStackValues)
1944	}
1945	return nil
1946}
1947
1948var vecExtractLanes = [...]struct {
1949	laneCeil   byte
1950	resultType ValueType
1951}{
1952	OpcodeVecI8x16ExtractLaneS: {laneCeil: 16, resultType: ValueTypeI32},
1953	OpcodeVecI8x16ExtractLaneU: {laneCeil: 16, resultType: ValueTypeI32},
1954	OpcodeVecI16x8ExtractLaneS: {laneCeil: 8, resultType: ValueTypeI32},
1955	OpcodeVecI16x8ExtractLaneU: {laneCeil: 8, resultType: ValueTypeI32},
1956	OpcodeVecI32x4ExtractLane:  {laneCeil: 4, resultType: ValueTypeI32},
1957	OpcodeVecI64x2ExtractLane:  {laneCeil: 2, resultType: ValueTypeI64},
1958	OpcodeVecF32x4ExtractLane:  {laneCeil: 4, resultType: ValueTypeF32},
1959	OpcodeVecF64x2ExtractLane:  {laneCeil: 2, resultType: ValueTypeF64},
1960}
1961
1962var vecReplaceLanes = [...]struct {
1963	laneCeil  byte
1964	paramType ValueType
1965}{
1966	OpcodeVecI8x16ReplaceLane: {laneCeil: 16, paramType: ValueTypeI32},
1967	OpcodeVecI16x8ReplaceLane: {laneCeil: 8, paramType: ValueTypeI32},
1968	OpcodeVecI32x4ReplaceLane: {laneCeil: 4, paramType: ValueTypeI32},
1969	OpcodeVecI64x2ReplaceLane: {laneCeil: 2, paramType: ValueTypeI64},
1970	OpcodeVecF32x4ReplaceLane: {laneCeil: 4, paramType: ValueTypeF32},
1971	OpcodeVecF64x2ReplaceLane: {laneCeil: 2, paramType: ValueTypeF64},
1972}
1973
1974var vecStoreLanes = [...]struct {
1975	alignMax uint32
1976	laneCeil byte
1977}{
1978	OpcodeVecV128Store64Lane: {alignMax: 64 / 8, laneCeil: 128 / 64},
1979	OpcodeVecV128Store32Lane: {alignMax: 32 / 8, laneCeil: 128 / 32},
1980	OpcodeVecV128Store16Lane: {alignMax: 16 / 8, laneCeil: 128 / 16},
1981	OpcodeVecV128Store8Lane:  {alignMax: 1, laneCeil: 128 / 8},
1982}
1983
1984var vecLoadLanes = [...]struct {
1985	alignMax uint32
1986	laneCeil byte
1987}{
1988	OpcodeVecV128Load64Lane: {alignMax: 64 / 8, laneCeil: 128 / 64},
1989	OpcodeVecV128Load32Lane: {alignMax: 32 / 8, laneCeil: 128 / 32},
1990	OpcodeVecV128Load16Lane: {alignMax: 16 / 8, laneCeil: 128 / 16},
1991	OpcodeVecV128Load8Lane:  {alignMax: 1, laneCeil: 128 / 8},
1992}
1993
1994var vecSplatValueTypes = [...]ValueType{
1995	OpcodeVecI8x16Splat: ValueTypeI32,
1996	OpcodeVecI16x8Splat: ValueTypeI32,
1997	OpcodeVecI32x4Splat: ValueTypeI32,
1998	OpcodeVecI64x2Splat: ValueTypeI64,
1999	OpcodeVecF32x4Splat: ValueTypeF32,
2000	OpcodeVecF64x2Splat: ValueTypeF64,
2001}
2002
2003type stacks struct {
2004	vs valueTypeStack
2005	cs controlBlockStack
2006	// ls is the label slice that is reused for each br_table instruction.
2007	ls []uint32
2008}
2009
2010func (sts *stacks) reset(functionType *FunctionType) {
2011	// Reset valueStack for reuse.
2012	sts.vs.stack = sts.vs.stack[:0]
2013	sts.vs.stackLimits = sts.vs.stackLimits[:0]
2014	sts.vs.maximumStackPointer = 0
2015	sts.cs.stack = sts.cs.stack[:0]
2016	sts.cs.stack = append(sts.cs.stack, controlBlock{blockType: functionType})
2017	sts.ls = sts.ls[:0]
2018}
2019
2020type controlBlockStack struct {
2021	stack []controlBlock
2022}
2023
2024func (s *controlBlockStack) pop() *controlBlock {
2025	tail := len(s.stack) - 1
2026	ret := &s.stack[tail]
2027	s.stack = s.stack[:tail]
2028	return ret
2029}
2030
2031func (s *controlBlockStack) push(startAt, elseAt, endAt uint64, blockType *FunctionType, blockTypeBytes uint64, op Opcode) {
2032	s.stack = append(s.stack, controlBlock{
2033		startAt:        startAt,
2034		elseAt:         elseAt,
2035		endAt:          endAt,
2036		blockType:      blockType,
2037		blockTypeBytes: blockTypeBytes,
2038		op:             op,
2039	})
2040}
2041
2042type valueTypeStack struct {
2043	stack               []ValueType
2044	stackLimits         []int
2045	maximumStackPointer int
2046	// requireStackValuesTmp is used in requireStackValues function to reduce the allocation.
2047	requireStackValuesTmp []ValueType
2048}
2049
2050// Only used in the analyzeFunction below.
2051const valueTypeUnknown = ValueType(0xFF)
2052
2053func (s *valueTypeStack) tryPop() (vt ValueType, limit int, ok bool) {
2054	if len(s.stackLimits) > 0 {
2055		limit = s.stackLimits[len(s.stackLimits)-1]
2056	}
2057	stackLen := len(s.stack)
2058	if stackLen <= limit {
2059		return
2060	} else if stackLen == limit+1 && s.stack[limit] == valueTypeUnknown {
2061		vt = valueTypeUnknown
2062		ok = true
2063		return
2064	} else {
2065		vt = s.stack[stackLen-1]
2066		s.stack = s.stack[:stackLen-1]
2067		ok = true
2068		return
2069	}
2070}
2071
2072func (s *valueTypeStack) pop() (ValueType, error) {
2073	if vt, limit, ok := s.tryPop(); ok {
2074		return vt, nil
2075	} else {
2076		return 0, fmt.Errorf("invalid operation: trying to pop at %d with limit %d", len(s.stack), limit)
2077	}
2078}
2079
2080// popAndVerifyType returns an error if the stack value is unexpected.
2081func (s *valueTypeStack) popAndVerifyType(expected ValueType) error {
2082	have, _, ok := s.tryPop()
2083	if !ok {
2084		return fmt.Errorf("%s missing", ValueTypeName(expected))
2085	}
2086	if have != expected && have != valueTypeUnknown && expected != valueTypeUnknown {
2087		return fmt.Errorf("type mismatch: expected %s, but was %s", ValueTypeName(expected), ValueTypeName(have))
2088	}
2089	return nil
2090}
2091
2092func (s *valueTypeStack) push(v ValueType) {
2093	s.stack = append(s.stack, v)
2094	if sp := len(s.stack); sp > s.maximumStackPointer {
2095		s.maximumStackPointer = sp
2096	}
2097}
2098
2099func (s *valueTypeStack) unreachable() {
2100	s.resetAtStackLimit()
2101	s.stack = append(s.stack, valueTypeUnknown)
2102}
2103
2104func (s *valueTypeStack) resetAtStackLimit() {
2105	if len(s.stackLimits) != 0 {
2106		s.stack = s.stack[:s.stackLimits[len(s.stackLimits)-1]]
2107	} else {
2108		s.stack = s.stack[:0]
2109	}
2110}
2111
2112func (s *valueTypeStack) popStackLimit() {
2113	if len(s.stackLimits) != 0 {
2114		s.stackLimits = s.stackLimits[:len(s.stackLimits)-1]
2115	}
2116}
2117
2118// pushStackLimit pushes the control frame's bottom of the stack.
2119func (s *valueTypeStack) pushStackLimit(params int) {
2120	limit := len(s.stack) - params
2121	s.stackLimits = append(s.stackLimits, limit)
2122}
2123
2124func (s *valueTypeStack) popParams(oc Opcode, want []ValueType, checkAboveLimit bool) error {
2125	return s.requireStackValues(true, InstructionName(oc), want, checkAboveLimit)
2126}
2127
2128func (s *valueTypeStack) popResults(oc Opcode, want []ValueType, checkAboveLimit bool) error {
2129	return s.requireStackValues(false, InstructionName(oc), want, checkAboveLimit)
2130}
2131
2132func (s *valueTypeStack) requireStackValues(
2133	isParam bool,
2134	context string,
2135	want []ValueType,
2136	checkAboveLimit bool,
2137) error {
2138	limit := 0
2139	if len(s.stackLimits) > 0 {
2140		limit = s.stackLimits[len(s.stackLimits)-1]
2141	}
2142	// Iterate backwards as we are comparing the desired slice against stack value types.
2143	countWanted := len(want)
2144
2145	// First, check if there are enough values on the stack.
2146	s.requireStackValuesTmp = s.requireStackValuesTmp[:0]
2147	for i := countWanted - 1; i >= 0; i-- {
2148		popped, _, ok := s.tryPop()
2149		if !ok {
2150			if len(s.requireStackValuesTmp) > len(want) {
2151				return typeCountError(isParam, context, s.requireStackValuesTmp, want)
2152			}
2153			return typeCountError(isParam, context, s.requireStackValuesTmp, want)
2154		}
2155		s.requireStackValuesTmp = append(s.requireStackValuesTmp, popped)
2156	}
2157
2158	// Now, check if there are too many values.
2159	if checkAboveLimit {
2160		if !(limit == len(s.stack) || (limit+1 == len(s.stack) && s.stack[limit] == valueTypeUnknown)) {
2161			return typeCountError(isParam, context, append(s.stack, want...), want)
2162		}
2163	}
2164
2165	// Finally, check the types of the values:
2166	for i, v := range s.requireStackValuesTmp {
2167		nextWant := want[countWanted-i-1] // have is in reverse order (stack)
2168		if v != nextWant && v != valueTypeUnknown && nextWant != valueTypeUnknown {
2169			return typeMismatchError(isParam, context, v, nextWant, i)
2170		}
2171	}
2172	return nil
2173}
2174
2175// typeMismatchError returns an error similar to go compiler's error on type mismatch.
2176func typeMismatchError(isParam bool, context string, have ValueType, want ValueType, i int) error {
2177	var ret strings.Builder
2178	ret.WriteString("cannot use ")
2179	ret.WriteString(ValueTypeName(have))
2180	if context != "" {
2181		ret.WriteString(" in ")
2182		ret.WriteString(context)
2183		ret.WriteString(" block")
2184	}
2185	if isParam {
2186		ret.WriteString(" as param")
2187	} else {
2188		ret.WriteString(" as result")
2189	}
2190	ret.WriteString("[")
2191	ret.WriteString(strconv.Itoa(i))
2192	ret.WriteString("] type ")
2193	ret.WriteString(ValueTypeName(want))
2194	return errors.New(ret.String())
2195}
2196
2197// typeCountError returns an error similar to go compiler's error on type count mismatch.
2198func typeCountError(isParam bool, context string, have []ValueType, want []ValueType) error {
2199	var ret strings.Builder
2200	if len(have) > len(want) {
2201		ret.WriteString("too many ")
2202	} else {
2203		ret.WriteString("not enough ")
2204	}
2205	if isParam {
2206		ret.WriteString("params")
2207	} else {
2208		ret.WriteString("results")
2209	}
2210	if context != "" {
2211		if isParam {
2212			ret.WriteString(" for ")
2213		} else {
2214			ret.WriteString(" in ")
2215		}
2216		ret.WriteString(context)
2217		ret.WriteString(" block")
2218	}
2219	ret.WriteString("\n\thave (")
2220	writeValueTypes(have, &ret)
2221	ret.WriteString(")\n\twant (")
2222	writeValueTypes(want, &ret)
2223	ret.WriteByte(')')
2224	return errors.New(ret.String())
2225}
2226
2227func writeValueTypes(vts []ValueType, ret *strings.Builder) {
2228	switch len(vts) {
2229	case 0:
2230	case 1:
2231		ret.WriteString(ValueTypeName(vts[0]))
2232	default:
2233		ret.WriteString(ValueTypeName(vts[0]))
2234		for _, vt := range vts[1:] {
2235			ret.WriteString(", ")
2236			ret.WriteString(ValueTypeName(vt))
2237		}
2238	}
2239}
2240
2241func (s *valueTypeStack) String() string {
2242	var typeStrs, limits []string
2243	for _, v := range s.stack {
2244		var str string
2245		if v == valueTypeUnknown {
2246			str = "unknown"
2247		} else {
2248			str = ValueTypeName(v)
2249		}
2250		typeStrs = append(typeStrs, str)
2251	}
2252	for _, d := range s.stackLimits {
2253		limits = append(limits, fmt.Sprintf("%d", d))
2254	}
2255	return fmt.Sprintf("{stack: [%s], limits: [%s]}",
2256		strings.Join(typeStrs, ", "), strings.Join(limits, ","))
2257}
2258
2259type controlBlock struct {
2260	startAt, elseAt, endAt uint64
2261	blockType              *FunctionType
2262	blockTypeBytes         uint64
2263	// op is zero when the outermost block
2264	op Opcode
2265}
2266
2267// DecodeBlockType decodes the type index from a positive 33-bit signed integer. Negative numbers indicate up to one
2268// WebAssembly 1.0 (20191205) compatible result type. Positive numbers are decoded when `enabledFeatures` include
2269// CoreFeatureMultiValue and include an index in the Module.TypeSection.
2270//
2271// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-blocktype
2272// See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/multi-value/Overview.md
2273func DecodeBlockType(types []FunctionType, r *bytes.Reader, enabledFeatures api.CoreFeatures) (*FunctionType, uint64, error) {
2274	raw, num, err := leb128.DecodeInt33AsInt64(r)
2275	if err != nil {
2276		return nil, 0, fmt.Errorf("decode int33: %w", err)
2277	}
2278
2279	var ret *FunctionType
2280	switch raw {
2281	case -64: // 0x40 in original byte = nil
2282		ret = blockType_v_v
2283	case -1: // 0x7f in original byte = i32
2284		ret = blockType_v_i32
2285	case -2: // 0x7e in original byte = i64
2286		ret = blockType_v_i64
2287	case -3: // 0x7d in original byte = f32
2288		ret = blockType_v_f32
2289	case -4: // 0x7c in original byte = f64
2290		ret = blockType_v_f64
2291	case -5: // 0x7b in original byte = v128
2292		ret = blockType_v_v128
2293	case -16: // 0x70 in original byte = funcref
2294		ret = blockType_v_funcref
2295	case -17: // 0x6f in original byte = externref
2296		ret = blockType_v_externref
2297	default:
2298		if err = enabledFeatures.RequireEnabled(api.CoreFeatureMultiValue); err != nil {
2299			return nil, num, fmt.Errorf("block with function type return invalid as %v", err)
2300		}
2301		if raw < 0 || (raw >= int64(len(types))) {
2302			return nil, 0, fmt.Errorf("type index out of range: %d", raw)
2303		}
2304		ret = &types[raw]
2305	}
2306	return ret, num, err
2307}
2308
2309// These block types are defined as globals in order to avoid allocations in DecodeBlockType.
2310var (
2311	blockType_v_v         = &FunctionType{}
2312	blockType_v_i32       = &FunctionType{Results: []ValueType{ValueTypeI32}, ResultNumInUint64: 1}
2313	blockType_v_i64       = &FunctionType{Results: []ValueType{ValueTypeI64}, ResultNumInUint64: 1}
2314	blockType_v_f32       = &FunctionType{Results: []ValueType{ValueTypeF32}, ResultNumInUint64: 1}
2315	blockType_v_f64       = &FunctionType{Results: []ValueType{ValueTypeF64}, ResultNumInUint64: 1}
2316	blockType_v_v128      = &FunctionType{Results: []ValueType{ValueTypeV128}, ResultNumInUint64: 2}
2317	blockType_v_funcref   = &FunctionType{Results: []ValueType{ValueTypeFuncref}, ResultNumInUint64: 1}
2318	blockType_v_externref = &FunctionType{Results: []ValueType{ValueTypeExternref}, ResultNumInUint64: 1}
2319)
2320
2321// SplitCallStack returns the input stack resliced to the count of params and
2322// results, or errors if it isn't long enough for either.
2323func SplitCallStack(ft *FunctionType, stack []uint64) (params []uint64, results []uint64, err error) {
2324	stackLen := len(stack)
2325	if n := ft.ParamNumInUint64; n > stackLen {
2326		return nil, nil, fmt.Errorf("need %d params, but stack size is %d", n, stackLen)
2327	} else if n > 0 {
2328		params = stack[:n]
2329	}
2330	if n := ft.ResultNumInUint64; n > stackLen {
2331		return nil, nil, fmt.Errorf("need %d results, but stack size is %d", n, stackLen)
2332	} else if n > 0 {
2333		results = stack[:n]
2334	}
2335	return
2336}