github.com/taubyte/vm-wasm-utils@v1.0.2/func_validation.go (about)

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