github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/wasm/func_validation.go (about)

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