wa-lang.org/wazero@v1.0.2/internal/wasm/func_validation.go (about)

     1  package wasm
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  	"strconv"
     8  	"strings"
     9  
    10  	"wa-lang.org/wazero/api"
    11  	"wa-lang.org/wazero/internal/leb128"
    12  )
    13  
    14  // The wazero specific limitation described at RATIONALE.md.
    15  const maximumValuesOnStack = 1 << 27
    16  
    17  // validateFunction validates the instruction sequence of a function.
    18  // following the specification https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#instructions%E2%91%A2.
    19  //
    20  // * idx is the index in the FunctionSection
    21  // * functions are the function index namespace, which is prefixed by imports. The value is the TypeSection index.
    22  // * globals are the global index namespace, which is prefixed by imports.
    23  // * memory is the potentially imported memory and can be nil.
    24  // * table is the potentially imported table and can be nil.
    25  // * declaredFunctionIndexes is the set of function indexes declared by declarative element segments which can be acceed by OpcodeRefFunc instruction.
    26  //
    27  // Returns an error if the instruction sequence is not valid,
    28  // or potentially it can exceed the maximum number of values on the stack.
    29  func (m *Module) validateFunction(enabledFeatures api.CoreFeatures, idx Index, functions []Index,
    30  	globals []*GlobalType, memory *Memory, tables []*Table, declaredFunctionIndexes map[Index]struct{},
    31  ) 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.LoadUint32(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.LoadUint32(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 api.CoreFeatures,
    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 false {
    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.LoadUint32(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.LoadInt32(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.LoadInt64(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.LoadUint32(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.LoadUint32(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.LoadUint32(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.IsEnabled(api.CoreFeatureReferenceTypes) {
   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.LoadUint32(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.LoadUint32(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.LoadUint32(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.RequireEnabled(api.CoreFeatureReferenceTypes); 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.RequireEnabled(api.CoreFeatureSignExtensionOps); 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.RequireEnabled(api.CoreFeatureSignExtensionOps); 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.RequireEnabled(api.CoreFeatureReferenceTypes); 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.LoadUint32(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.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
   843  				return fmt.Errorf("%s is invalid as %v", InstructionName(op), err)
   844  			}
   845  			pc++
   846  			tableIndex, num, err := leb128.LoadUint32(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  			// A misc opcode is encoded as an unsigned variable 32-bit integer.
   872  			miscOp32, num, err := leb128.LoadUint32(body[pc:])
   873  			if err != nil {
   874  				return fmt.Errorf("failed to read misc opcode: %v", err)
   875  			}
   876  			pc += num - 1
   877  			miscOpcode := byte(miscOp32)
   878  			// If the misc opcode is beyond byte range, it is highly likely this is an invalid binary, or
   879  			// it is due to the new opcode from a new proposal. In the latter case, we have to
   880  			// change the alias type of OpcodeMisc (which is currently byte) to uint32.
   881  			if uint32(byte(miscOp32)) != miscOp32 {
   882  				return fmt.Errorf("invalid misc opcode: %#x", miscOp32)
   883  			}
   884  			if miscOpcode >= OpcodeMiscI32TruncSatF32S && miscOpcode <= OpcodeMiscI64TruncSatF64U {
   885  				if err := enabledFeatures.RequireEnabled(api.CoreFeatureNonTrappingFloatToIntConversion); err != nil {
   886  					return fmt.Errorf("%s invalid as %v", miscInstructionNames[miscOpcode], err)
   887  				}
   888  				var inType, outType ValueType
   889  				switch miscOpcode {
   890  				case OpcodeMiscI32TruncSatF32S, OpcodeMiscI32TruncSatF32U:
   891  					inType, outType = ValueTypeF32, ValueTypeI32
   892  				case OpcodeMiscI32TruncSatF64S, OpcodeMiscI32TruncSatF64U:
   893  					inType, outType = ValueTypeF64, ValueTypeI32
   894  				case OpcodeMiscI64TruncSatF32S, OpcodeMiscI64TruncSatF32U:
   895  					inType, outType = ValueTypeF32, ValueTypeI64
   896  				case OpcodeMiscI64TruncSatF64S, OpcodeMiscI64TruncSatF64U:
   897  					inType, outType = ValueTypeF64, ValueTypeI64
   898  				}
   899  				if err := valueTypeStack.popAndVerifyType(inType); err != nil {
   900  					return fmt.Errorf("cannot pop the operand for %s: %v", miscInstructionNames[miscOpcode], err)
   901  				}
   902  				valueTypeStack.push(outType)
   903  			} else if miscOpcode >= OpcodeMiscMemoryInit && miscOpcode <= OpcodeMiscTableCopy {
   904  				if err := enabledFeatures.RequireEnabled(api.CoreFeatureBulkMemoryOperations); err != nil {
   905  					return fmt.Errorf("%s invalid as %v", miscInstructionNames[miscOpcode], err)
   906  				}
   907  				var params []ValueType
   908  				// Handle opcodes added in bulk-memory-operations/WebAssembly 2.0.
   909  				switch miscOpcode {
   910  				case OpcodeMiscDataDrop:
   911  					if m.DataCountSection == nil {
   912  						return fmt.Errorf("%s requires data count section", MiscInstructionName(miscOpcode))
   913  					}
   914  
   915  					// We need to read the index to the data section.
   916  					pc++
   917  					index, num, err := leb128.LoadUint32(body[pc:])
   918  					if err != nil {
   919  						return fmt.Errorf("failed to read data segment index for %s: %v", MiscInstructionName(miscOpcode), err)
   920  					}
   921  					if int(index) >= len(m.DataSection) {
   922  						return fmt.Errorf("index %d out of range of data section(len=%d)", index, len(m.DataSection))
   923  					}
   924  					pc += num - 1
   925  				case OpcodeMiscMemoryInit, OpcodeMiscMemoryCopy, OpcodeMiscMemoryFill:
   926  					if memory == nil {
   927  						return fmt.Errorf("memory must exist for %s", MiscInstructionName(miscOpcode))
   928  					}
   929  					params = []ValueType{ValueTypeI32, ValueTypeI32, ValueTypeI32}
   930  
   931  					if miscOpcode == OpcodeMiscMemoryInit {
   932  						if m.DataCountSection == nil {
   933  							return fmt.Errorf("%s requires data count section", MiscInstructionName(miscOpcode))
   934  						}
   935  
   936  						// We need to read the index to the data section.
   937  						pc++
   938  						index, num, err := leb128.LoadUint32(body[pc:])
   939  						if err != nil {
   940  							return fmt.Errorf("failed to read data segment index for %s: %v", MiscInstructionName(miscOpcode), err)
   941  						}
   942  						if int(index) >= len(m.DataSection) {
   943  							return fmt.Errorf("index %d out of range of data section(len=%d)", index, len(m.DataSection))
   944  						}
   945  						pc += num - 1
   946  					}
   947  
   948  					pc++
   949  					val, num, err := leb128.LoadUint32(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  					if miscOpcode == OpcodeMiscMemoryCopy {
   957  						pc++
   958  						// memory.copy needs two memory index which are reserved as zero.
   959  						val, num, err := leb128.LoadUint32(body[pc:])
   960  						if err != nil {
   961  							return fmt.Errorf("failed to read memory index for %s: %v", MiscInstructionName(miscOpcode), err)
   962  						}
   963  						if val != 0 || num != 1 {
   964  							return fmt.Errorf("%s reserved byte must be zero encoded with 1 byte", MiscInstructionName(miscOpcode))
   965  						}
   966  					}
   967  
   968  				case OpcodeMiscTableInit:
   969  					params = []ValueType{ValueTypeI32, ValueTypeI32, ValueTypeI32}
   970  					pc++
   971  					elementIndex, num, err := leb128.LoadUint32(body[pc:])
   972  					if err != nil {
   973  						return fmt.Errorf("failed to read element segment index for %s: %v", MiscInstructionName(miscOpcode), err)
   974  					}
   975  					if int(elementIndex) >= len(m.ElementSection) {
   976  						return fmt.Errorf("index %d out of range of element section(len=%d)", elementIndex, len(m.ElementSection))
   977  					}
   978  					pc += num
   979  
   980  					tableIndex, num, err := leb128.LoadUint32(body[pc:])
   981  					if err != nil {
   982  						return fmt.Errorf("failed to read source table index for %s: %v", MiscInstructionName(miscOpcode), err)
   983  					}
   984  					if tableIndex != 0 {
   985  						if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
   986  							return fmt.Errorf("source table index must be zero for %s as %v", MiscInstructionName(miscOpcode), err)
   987  						}
   988  					}
   989  					if tableIndex >= uint32(len(tables)) {
   990  						return fmt.Errorf("table of index %d not found", tableIndex)
   991  					}
   992  
   993  					if m.ElementSection[elementIndex].Type != tables[tableIndex].Type {
   994  						return fmt.Errorf("type mismatch for table.init: element type %s does not match table type %s",
   995  							RefTypeName(m.ElementSection[elementIndex].Type),
   996  							RefTypeName(tables[tableIndex].Type),
   997  						)
   998  					}
   999  					pc += num - 1
  1000  				case OpcodeMiscElemDrop:
  1001  					pc++
  1002  					elementIndex, num, err := leb128.LoadUint32(body[pc:])
  1003  					if err != nil {
  1004  						return fmt.Errorf("failed to read element segment index for %s: %v", MiscInstructionName(miscOpcode), err)
  1005  					} else if int(elementIndex) >= len(m.ElementSection) {
  1006  						return fmt.Errorf("index %d out of range of element section(len=%d)", elementIndex, len(m.ElementSection))
  1007  					}
  1008  					pc += num - 1
  1009  				case OpcodeMiscTableCopy:
  1010  					params = []ValueType{ValueTypeI32, ValueTypeI32, ValueTypeI32}
  1011  					pc++
  1012  
  1013  					dstTableIndex, num, err := leb128.LoadUint32(body[pc:])
  1014  					if err != nil {
  1015  						return fmt.Errorf("failed to read destination table index for %s: %v", MiscInstructionName(miscOpcode), err)
  1016  					}
  1017  					if dstTableIndex != 0 {
  1018  						if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
  1019  							return fmt.Errorf("destination table index must be zero for %s as %v", MiscInstructionName(miscOpcode), err)
  1020  						}
  1021  					}
  1022  					if dstTableIndex >= uint32(len(tables)) {
  1023  						return fmt.Errorf("table of index %d not found", dstTableIndex)
  1024  					}
  1025  					pc += num
  1026  
  1027  					srcTableIndex, num, err := leb128.LoadUint32(body[pc:])
  1028  					if err != nil {
  1029  						return fmt.Errorf("failed to read source table index for %s: %v", MiscInstructionName(miscOpcode), err)
  1030  					}
  1031  					if srcTableIndex != 0 {
  1032  						if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
  1033  							return fmt.Errorf("source table index must be zero for %s as %v", MiscInstructionName(miscOpcode), err)
  1034  						}
  1035  					}
  1036  					if srcTableIndex >= uint32(len(tables)) {
  1037  						return fmt.Errorf("table of index %d not found", srcTableIndex)
  1038  					}
  1039  
  1040  					if tables[srcTableIndex].Type != tables[dstTableIndex].Type {
  1041  						return fmt.Errorf("table type mismatch for table.copy: %s (src) != %s (dst)",
  1042  							RefTypeName(tables[srcTableIndex].Type), RefTypeName(tables[dstTableIndex].Type))
  1043  					}
  1044  
  1045  					pc += num - 1
  1046  				}
  1047  				for _, p := range params {
  1048  					if err := valueTypeStack.popAndVerifyType(p); err != nil {
  1049  						return fmt.Errorf("cannot pop the operand for %s: %v", miscInstructionNames[miscOpcode], err)
  1050  					}
  1051  				}
  1052  			} else if miscOpcode >= OpcodeMiscTableGrow && miscOpcode <= OpcodeMiscTableFill {
  1053  				if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
  1054  					return fmt.Errorf("%s invalid as %v", miscInstructionNames[miscOpcode], err)
  1055  				}
  1056  
  1057  				pc++
  1058  				tableIndex, num, err := leb128.LoadUint32(body[pc:])
  1059  				if err != nil {
  1060  					return fmt.Errorf("failed to read table index for %s: %v", MiscInstructionName(miscOpcode), err)
  1061  				}
  1062  				if tableIndex >= uint32(len(tables)) {
  1063  					return fmt.Errorf("table of index %d not found", tableIndex)
  1064  				}
  1065  				pc += num - 1
  1066  
  1067  				var params, results []ValueType
  1068  				reftype := tables[tableIndex].Type
  1069  				if miscOpcode == OpcodeMiscTableGrow {
  1070  					params = []ValueType{ValueTypeI32, reftype}
  1071  					results = []ValueType{ValueTypeI32}
  1072  				} else if miscOpcode == OpcodeMiscTableSize {
  1073  					results = []ValueType{ValueTypeI32}
  1074  				} else if miscOpcode == OpcodeMiscTableFill {
  1075  					params = []ValueType{ValueTypeI32, reftype, ValueTypeI32}
  1076  				}
  1077  
  1078  				for _, p := range params {
  1079  					if err := valueTypeStack.popAndVerifyType(p); err != nil {
  1080  						return fmt.Errorf("cannot pop the operand for %s: %v", miscInstructionNames[miscOpcode], err)
  1081  					}
  1082  				}
  1083  				for _, r := range results {
  1084  					valueTypeStack.push(r)
  1085  				}
  1086  			}
  1087  		} else if op == OpcodeVecPrefix {
  1088  			pc++
  1089  			// Vector instructions come with two bytes where the first byte is always OpcodeVecPrefix,
  1090  			// and the second byte determines the actual instruction.
  1091  			vecOpcode := body[pc]
  1092  			if err := enabledFeatures.RequireEnabled(api.CoreFeatureSIMD); err != nil {
  1093  				return fmt.Errorf("%s invalid as %v", vectorInstructionName[vecOpcode], err)
  1094  			}
  1095  
  1096  			switch vecOpcode {
  1097  			case OpcodeVecV128Const:
  1098  				// Read 128-bit = 16 bytes constants
  1099  				if int(pc+16) >= len(body) {
  1100  					return fmt.Errorf("cannot read constant vector value for %s", vectorInstructionName[vecOpcode])
  1101  				}
  1102  				pc += 16
  1103  				valueTypeStack.push(ValueTypeV128)
  1104  			case OpcodeVecV128AnyTrue, OpcodeVecI8x16AllTrue, OpcodeVecI16x8AllTrue, OpcodeVecI32x4AllTrue, OpcodeVecI64x2AllTrue,
  1105  				OpcodeVecI8x16BitMask, OpcodeVecI16x8BitMask, OpcodeVecI32x4BitMask, OpcodeVecI64x2BitMask:
  1106  				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
  1107  					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
  1108  				}
  1109  				valueTypeStack.push(ValueTypeI32)
  1110  			case OpcodeVecV128Load, OpcodeVecV128Load8x8s, OpcodeVecV128Load8x8u, OpcodeVecV128Load16x4s, OpcodeVecV128Load16x4u,
  1111  				OpcodeVecV128Load32x2s, OpcodeVecV128Load32x2u, OpcodeVecV128Load8Splat, OpcodeVecV128Load16Splat,
  1112  				OpcodeVecV128Load32Splat, OpcodeVecV128Load64Splat,
  1113  				OpcodeVecV128Load32zero, OpcodeVecV128Load64zero:
  1114  				if memory == nil && !code.IsHostFunction {
  1115  					return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode))
  1116  				}
  1117  				pc++
  1118  				align, _, read, err := readMemArg(pc, body)
  1119  				if err != nil {
  1120  					return err
  1121  				}
  1122  				pc += read - 1
  1123  				var maxAlign uint32
  1124  				switch vecOpcode {
  1125  				case OpcodeVecV128Load:
  1126  					maxAlign = 128 / 8
  1127  				case OpcodeVecV128Load8x8s, OpcodeVecV128Load8x8u, OpcodeVecV128Load16x4s, OpcodeVecV128Load16x4u,
  1128  					OpcodeVecV128Load32x2s, OpcodeVecV128Load32x2u:
  1129  					maxAlign = 64 / 8
  1130  				case OpcodeVecV128Load8Splat:
  1131  					maxAlign = 1
  1132  				case OpcodeVecV128Load16Splat:
  1133  					maxAlign = 16 / 8
  1134  				case OpcodeVecV128Load32Splat:
  1135  					maxAlign = 32 / 8
  1136  				case OpcodeVecV128Load64Splat:
  1137  					maxAlign = 64 / 8
  1138  				case OpcodeVecV128Load32zero:
  1139  					maxAlign = 32 / 8
  1140  				case OpcodeVecV128Load64zero:
  1141  					maxAlign = 64 / 8
  1142  				}
  1143  
  1144  				if 1<<align > maxAlign {
  1145  					return fmt.Errorf("invalid memory alignment %d for %s", align, VectorInstructionName(vecOpcode))
  1146  				}
  1147  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
  1148  					return fmt.Errorf("cannot pop the operand for %s: %v", VectorInstructionName(vecOpcode), err)
  1149  				}
  1150  				valueTypeStack.push(ValueTypeV128)
  1151  			case OpcodeVecV128Store:
  1152  				if memory == nil && !code.IsHostFunction {
  1153  					return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode))
  1154  				}
  1155  				pc++
  1156  				align, _, read, err := readMemArg(pc, body)
  1157  				if err != nil {
  1158  					return err
  1159  				}
  1160  				pc += read - 1
  1161  				if 1<<align > 128/8 {
  1162  					return fmt.Errorf("invalid memory alignment %d for %s", align, OpcodeVecV128StoreName)
  1163  				}
  1164  				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
  1165  					return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeVecV128StoreName, err)
  1166  				}
  1167  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
  1168  					return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeVecV128StoreName, err)
  1169  				}
  1170  			case OpcodeVecV128Load8Lane, OpcodeVecV128Load16Lane, OpcodeVecV128Load32Lane, OpcodeVecV128Load64Lane:
  1171  				if memory == nil && !code.IsHostFunction {
  1172  					return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode))
  1173  				}
  1174  				attr := vecLoadLanes[vecOpcode]
  1175  				pc++
  1176  				align, _, read, err := readMemArg(pc, body)
  1177  				if err != nil {
  1178  					return err
  1179  				}
  1180  				if 1<<align > attr.alignMax {
  1181  					return fmt.Errorf("invalid memory alignment %d for %s", align, vectorInstructionName[vecOpcode])
  1182  				}
  1183  				pc += read
  1184  				if pc >= uint64(len(body)) {
  1185  					return fmt.Errorf("lane for %s not found", OpcodeVecV128Load64LaneName)
  1186  				}
  1187  				lane := body[pc]
  1188  				if lane >= attr.laneCeil {
  1189  					return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode])
  1190  				}
  1191  				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
  1192  					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
  1193  				}
  1194  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
  1195  					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
  1196  				}
  1197  				valueTypeStack.push(ValueTypeV128)
  1198  			case OpcodeVecV128Store8Lane, OpcodeVecV128Store16Lane, OpcodeVecV128Store32Lane, OpcodeVecV128Store64Lane:
  1199  				if memory == nil && !code.IsHostFunction {
  1200  					return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode))
  1201  				}
  1202  				attr := vecStoreLanes[vecOpcode]
  1203  				pc++
  1204  				align, _, read, err := readMemArg(pc, body)
  1205  				if err != nil {
  1206  					return err
  1207  				}
  1208  				if 1<<align > attr.alignMax {
  1209  					return fmt.Errorf("invalid memory alignment %d for %s", align, vectorInstructionName[vecOpcode])
  1210  				}
  1211  				pc += read
  1212  				if pc >= uint64(len(body)) {
  1213  					return fmt.Errorf("lane for %s not found", vectorInstructionName[vecOpcode])
  1214  				}
  1215  				lane := body[pc]
  1216  				if lane >= attr.laneCeil {
  1217  					return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode])
  1218  				}
  1219  				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
  1220  					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
  1221  				}
  1222  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
  1223  					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
  1224  				}
  1225  			case OpcodeVecI8x16ExtractLaneS,
  1226  				OpcodeVecI8x16ExtractLaneU,
  1227  				OpcodeVecI16x8ExtractLaneS,
  1228  				OpcodeVecI16x8ExtractLaneU,
  1229  				OpcodeVecI32x4ExtractLane,
  1230  				OpcodeVecI64x2ExtractLane,
  1231  				OpcodeVecF32x4ExtractLane,
  1232  				OpcodeVecF64x2ExtractLane:
  1233  				pc++
  1234  				if pc >= uint64(len(body)) {
  1235  					return fmt.Errorf("lane for %s not found", vectorInstructionName[vecOpcode])
  1236  				}
  1237  				attr := vecExtractLanes[vecOpcode]
  1238  				lane := body[pc]
  1239  				if lane >= attr.laneCeil {
  1240  					return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode])
  1241  				}
  1242  				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
  1243  					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
  1244  				}
  1245  				valueTypeStack.push(attr.resultType)
  1246  			case OpcodeVecI8x16ReplaceLane, OpcodeVecI16x8ReplaceLane, OpcodeVecI32x4ReplaceLane,
  1247  				OpcodeVecI64x2ReplaceLane, OpcodeVecF32x4ReplaceLane, OpcodeVecF64x2ReplaceLane:
  1248  				pc++
  1249  				if pc >= uint64(len(body)) {
  1250  					return fmt.Errorf("lane for %s not found", vectorInstructionName[vecOpcode])
  1251  				}
  1252  				attr := vecReplaceLanes[vecOpcode]
  1253  				lane := body[pc]
  1254  				if lane >= attr.laneCeil {
  1255  					return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode])
  1256  				}
  1257  				if err := valueTypeStack.popAndVerifyType(attr.paramType); err != nil {
  1258  					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
  1259  				}
  1260  				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
  1261  					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
  1262  				}
  1263  				valueTypeStack.push(ValueTypeV128)
  1264  			case OpcodeVecI8x16Splat, OpcodeVecI16x8Splat, OpcodeVecI32x4Splat,
  1265  				OpcodeVecI64x2Splat, OpcodeVecF32x4Splat, OpcodeVecF64x2Splat:
  1266  				tp := vecSplatValueTypes[vecOpcode]
  1267  				if err := valueTypeStack.popAndVerifyType(tp); err != nil {
  1268  					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
  1269  				}
  1270  				valueTypeStack.push(ValueTypeV128)
  1271  			case OpcodeVecI8x16Swizzle, OpcodeVecV128And, OpcodeVecV128Or, OpcodeVecV128Xor, OpcodeVecV128AndNot:
  1272  				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
  1273  					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
  1274  				}
  1275  				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
  1276  					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
  1277  				}
  1278  				valueTypeStack.push(ValueTypeV128)
  1279  			case OpcodeVecV128Bitselect:
  1280  				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
  1281  					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
  1282  				}
  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  				valueTypeStack.push(ValueTypeV128)
  1290  			case OpcodeVecV128Not:
  1291  				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
  1292  					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
  1293  				}
  1294  				valueTypeStack.push(ValueTypeV128)
  1295  			case OpcodeVecV128i8x16Shuffle:
  1296  				pc++
  1297  				if pc+15 >= uint64(len(body)) {
  1298  					return fmt.Errorf("16 lane indexes for %s not found", vectorInstructionName[vecOpcode])
  1299  				}
  1300  				lanes := body[pc : pc+16]
  1301  				for i, l := range lanes {
  1302  					if l >= 32 {
  1303  						return fmt.Errorf("invalid lane index[%d] %d >= %d for %s", i, l, 32, vectorInstructionName[vecOpcode])
  1304  					}
  1305  				}
  1306  				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
  1307  					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
  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  				valueTypeStack.push(ValueTypeV128)
  1313  				pc += 15
  1314  			case OpcodeVecI8x16Shl, OpcodeVecI8x16ShrS, OpcodeVecI8x16ShrU,
  1315  				OpcodeVecI16x8Shl, OpcodeVecI16x8ShrS, OpcodeVecI16x8ShrU,
  1316  				OpcodeVecI32x4Shl, OpcodeVecI32x4ShrS, OpcodeVecI32x4ShrU,
  1317  				OpcodeVecI64x2Shl, OpcodeVecI64x2ShrS, OpcodeVecI64x2ShrU:
  1318  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
  1319  					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
  1320  				}
  1321  				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
  1322  					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
  1323  				}
  1324  				valueTypeStack.push(ValueTypeV128)
  1325  			case OpcodeVecI8x16Eq, OpcodeVecI8x16Ne, OpcodeVecI8x16LtS, OpcodeVecI8x16LtU, OpcodeVecI8x16GtS,
  1326  				OpcodeVecI8x16GtU, OpcodeVecI8x16LeS, OpcodeVecI8x16LeU, OpcodeVecI8x16GeS, OpcodeVecI8x16GeU,
  1327  				OpcodeVecI16x8Eq, OpcodeVecI16x8Ne, OpcodeVecI16x8LtS, OpcodeVecI16x8LtU, OpcodeVecI16x8GtS,
  1328  				OpcodeVecI16x8GtU, OpcodeVecI16x8LeS, OpcodeVecI16x8LeU, OpcodeVecI16x8GeS, OpcodeVecI16x8GeU,
  1329  				OpcodeVecI32x4Eq, OpcodeVecI32x4Ne, OpcodeVecI32x4LtS, OpcodeVecI32x4LtU, OpcodeVecI32x4GtS,
  1330  				OpcodeVecI32x4GtU, OpcodeVecI32x4LeS, OpcodeVecI32x4LeU, OpcodeVecI32x4GeS, OpcodeVecI32x4GeU,
  1331  				OpcodeVecI64x2Eq, OpcodeVecI64x2Ne, OpcodeVecI64x2LtS, OpcodeVecI64x2GtS, OpcodeVecI64x2LeS,
  1332  				OpcodeVecI64x2GeS, OpcodeVecF32x4Eq, OpcodeVecF32x4Ne, OpcodeVecF32x4Lt, OpcodeVecF32x4Gt,
  1333  				OpcodeVecF32x4Le, OpcodeVecF32x4Ge, OpcodeVecF64x2Eq, OpcodeVecF64x2Ne, OpcodeVecF64x2Lt,
  1334  				OpcodeVecF64x2Gt, OpcodeVecF64x2Le, OpcodeVecF64x2Ge,
  1335  				OpcodeVecI32x4DotI16x8S,
  1336  				OpcodeVecI8x16NarrowI16x8S, OpcodeVecI8x16NarrowI16x8U, OpcodeVecI16x8NarrowI32x4S, OpcodeVecI16x8NarrowI32x4U:
  1337  				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
  1338  					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
  1339  				}
  1340  				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
  1341  					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
  1342  				}
  1343  				valueTypeStack.push(ValueTypeV128)
  1344  			case OpcodeVecI8x16Neg, OpcodeVecI16x8Neg, OpcodeVecI32x4Neg, OpcodeVecI64x2Neg, OpcodeVecF32x4Neg, OpcodeVecF64x2Neg,
  1345  				OpcodeVecF32x4Sqrt, OpcodeVecF64x2Sqrt,
  1346  				OpcodeVecI8x16Abs, OpcodeVecI8x16Popcnt, OpcodeVecI16x8Abs, OpcodeVecI32x4Abs, OpcodeVecI64x2Abs,
  1347  				OpcodeVecF32x4Abs, OpcodeVecF64x2Abs,
  1348  				OpcodeVecF32x4Ceil, OpcodeVecF32x4Floor, OpcodeVecF32x4Trunc, OpcodeVecF32x4Nearest,
  1349  				OpcodeVecF64x2Ceil, OpcodeVecF64x2Floor, OpcodeVecF64x2Trunc, OpcodeVecF64x2Nearest,
  1350  				OpcodeVecI16x8ExtendLowI8x16S, OpcodeVecI16x8ExtendHighI8x16S, OpcodeVecI16x8ExtendLowI8x16U, OpcodeVecI16x8ExtendHighI8x16U,
  1351  				OpcodeVecI32x4ExtendLowI16x8S, OpcodeVecI32x4ExtendHighI16x8S, OpcodeVecI32x4ExtendLowI16x8U, OpcodeVecI32x4ExtendHighI16x8U,
  1352  				OpcodeVecI64x2ExtendLowI32x4S, OpcodeVecI64x2ExtendHighI32x4S, OpcodeVecI64x2ExtendLowI32x4U, OpcodeVecI64x2ExtendHighI32x4U,
  1353  				OpcodeVecI16x8ExtaddPairwiseI8x16S, OpcodeVecI16x8ExtaddPairwiseI8x16U,
  1354  				OpcodeVecI32x4ExtaddPairwiseI16x8S, OpcodeVecI32x4ExtaddPairwiseI16x8U,
  1355  				OpcodeVecF64x2PromoteLowF32x4Zero, OpcodeVecF32x4DemoteF64x2Zero,
  1356  				OpcodeVecF32x4ConvertI32x4S, OpcodeVecF32x4ConvertI32x4U,
  1357  				OpcodeVecF64x2ConvertLowI32x4S, OpcodeVecF64x2ConvertLowI32x4U,
  1358  				OpcodeVecI32x4TruncSatF32x4S, OpcodeVecI32x4TruncSatF32x4U, OpcodeVecI32x4TruncSatF64x2SZero, OpcodeVecI32x4TruncSatF64x2UZero:
  1359  				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
  1360  					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
  1361  				}
  1362  				valueTypeStack.push(ValueTypeV128)
  1363  
  1364  			case OpcodeVecI8x16Add, OpcodeVecI8x16AddSatS, OpcodeVecI8x16AddSatU, OpcodeVecI8x16Sub, OpcodeVecI8x16SubSatS, OpcodeVecI8x16SubSatU,
  1365  				OpcodeVecI16x8Add, OpcodeVecI16x8AddSatS, OpcodeVecI16x8AddSatU, OpcodeVecI16x8Sub, OpcodeVecI16x8SubSatS, OpcodeVecI16x8SubSatU, OpcodeVecI16x8Mul,
  1366  				OpcodeVecI32x4Add, OpcodeVecI32x4Sub, OpcodeVecI32x4Mul,
  1367  				OpcodeVecI64x2Add, OpcodeVecI64x2Sub, OpcodeVecI64x2Mul,
  1368  				OpcodeVecF32x4Add, OpcodeVecF32x4Sub, OpcodeVecF32x4Mul, OpcodeVecF32x4Div,
  1369  				OpcodeVecF64x2Add, OpcodeVecF64x2Sub, OpcodeVecF64x2Mul, OpcodeVecF64x2Div,
  1370  				OpcodeVecI8x16MinS, OpcodeVecI8x16MinU, OpcodeVecI8x16MaxS, OpcodeVecI8x16MaxU,
  1371  				OpcodeVecI8x16AvgrU,
  1372  				OpcodeVecI16x8MinS, OpcodeVecI16x8MinU, OpcodeVecI16x8MaxS, OpcodeVecI16x8MaxU,
  1373  				OpcodeVecI16x8AvgrU,
  1374  				OpcodeVecI32x4MinS, OpcodeVecI32x4MinU, OpcodeVecI32x4MaxS, OpcodeVecI32x4MaxU,
  1375  				OpcodeVecF32x4Min, OpcodeVecF32x4Max, OpcodeVecF64x2Min, OpcodeVecF64x2Max,
  1376  				OpcodeVecF32x4Pmin, OpcodeVecF32x4Pmax, OpcodeVecF64x2Pmin, OpcodeVecF64x2Pmax,
  1377  				OpcodeVecI16x8Q15mulrSatS,
  1378  				OpcodeVecI16x8ExtMulLowI8x16S, OpcodeVecI16x8ExtMulHighI8x16S, OpcodeVecI16x8ExtMulLowI8x16U, OpcodeVecI16x8ExtMulHighI8x16U,
  1379  				OpcodeVecI32x4ExtMulLowI16x8S, OpcodeVecI32x4ExtMulHighI16x8S, OpcodeVecI32x4ExtMulLowI16x8U, OpcodeVecI32x4ExtMulHighI16x8U,
  1380  				OpcodeVecI64x2ExtMulLowI32x4S, OpcodeVecI64x2ExtMulHighI32x4S, OpcodeVecI64x2ExtMulLowI32x4U, OpcodeVecI64x2ExtMulHighI32x4U:
  1381  				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
  1382  					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
  1383  				}
  1384  				if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
  1385  					return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
  1386  				}
  1387  				valueTypeStack.push(ValueTypeV128)
  1388  			default:
  1389  				return fmt.Errorf("TODO: SIMD instruction %s will be implemented in #506", vectorInstructionName[vecOpcode])
  1390  			}
  1391  		} else if op == OpcodeBlock {
  1392  			bt, num, err := DecodeBlockType(types, bytes.NewReader(body[pc+1:]), enabledFeatures)
  1393  			if err != nil {
  1394  				return fmt.Errorf("read block: %w", err)
  1395  			}
  1396  			controlBlockStack = append(controlBlockStack, &controlBlock{
  1397  				startAt:        pc,
  1398  				blockType:      bt,
  1399  				blockTypeBytes: num,
  1400  			})
  1401  			if err = valueTypeStack.popParams(op, bt.Params, false); err != nil {
  1402  				return err
  1403  			}
  1404  			// Plus we have to push any block params again.
  1405  			for _, p := range bt.Params {
  1406  				valueTypeStack.push(p)
  1407  			}
  1408  			valueTypeStack.pushStackLimit(len(bt.Params))
  1409  			pc += num
  1410  		} else if op == OpcodeLoop {
  1411  			bt, num, err := DecodeBlockType(types, bytes.NewReader(body[pc+1:]), enabledFeatures)
  1412  			if err != nil {
  1413  				return fmt.Errorf("read block: %w", err)
  1414  			}
  1415  			controlBlockStack = append(controlBlockStack, &controlBlock{
  1416  				startAt:        pc,
  1417  				blockType:      bt,
  1418  				blockTypeBytes: num,
  1419  				op:             op,
  1420  			})
  1421  			if err = valueTypeStack.popParams(op, bt.Params, false); err != nil {
  1422  				return err
  1423  			}
  1424  			// Plus we have to push any block params again.
  1425  			for _, p := range bt.Params {
  1426  				valueTypeStack.push(p)
  1427  			}
  1428  			valueTypeStack.pushStackLimit(len(bt.Params))
  1429  			pc += num
  1430  		} else if op == OpcodeIf {
  1431  			bt, num, err := DecodeBlockType(types, bytes.NewReader(body[pc+1:]), enabledFeatures)
  1432  			if err != nil {
  1433  				return fmt.Errorf("read block: %w", err)
  1434  			}
  1435  			controlBlockStack = append(controlBlockStack, &controlBlock{
  1436  				startAt:        pc,
  1437  				blockType:      bt,
  1438  				blockTypeBytes: num,
  1439  				op:             op,
  1440  			})
  1441  			if err = valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
  1442  				return fmt.Errorf("cannot pop the operand for 'if': %v", err)
  1443  			}
  1444  			if err = valueTypeStack.popParams(op, bt.Params, false); err != nil {
  1445  				return err
  1446  			}
  1447  			// Plus we have to push any block params again.
  1448  			for _, p := range bt.Params {
  1449  				valueTypeStack.push(p)
  1450  			}
  1451  			valueTypeStack.pushStackLimit(len(bt.Params))
  1452  			pc += num
  1453  		} else if op == OpcodeElse {
  1454  			bl := controlBlockStack[len(controlBlockStack)-1]
  1455  			bl.elseAt = pc
  1456  			// Check the type soundness of the instructions *before* entering this else Op.
  1457  			if err := valueTypeStack.popResults(OpcodeIf, bl.blockType.Results, true); err != nil {
  1458  				return err
  1459  			}
  1460  			// Before entering instructions inside else, we pop all the values pushed by then block.
  1461  			valueTypeStack.resetAtStackLimit()
  1462  			// Plus we have to push any block params again.
  1463  			for _, p := range bl.blockType.Params {
  1464  				valueTypeStack.push(p)
  1465  			}
  1466  		} else if op == OpcodeEnd {
  1467  			bl := controlBlockStack[len(controlBlockStack)-1]
  1468  			bl.endAt = pc
  1469  			controlBlockStack = controlBlockStack[:len(controlBlockStack)-1]
  1470  
  1471  			// OpcodeEnd can end a block or the function itself. Check to see what it is:
  1472  
  1473  			ifMissingElse := bl.op == OpcodeIf && bl.elseAt <= bl.startAt
  1474  			if ifMissingElse {
  1475  				// If this is the end of block without else, the number of block's results and params must be same.
  1476  				// Otherwise, the value stack would result in the inconsistent state at runtime.
  1477  				if !bytes.Equal(bl.blockType.Results, bl.blockType.Params) {
  1478  					return typeCountError(false, OpcodeElseName, bl.blockType.Params, bl.blockType.Results)
  1479  				}
  1480  				// -1 skips else, to handle if block without else properly.
  1481  				bl.elseAt = bl.endAt - 1
  1482  			}
  1483  
  1484  			// Determine the block context
  1485  			ctx := "" // the outer-most block: the function return
  1486  			if bl.op == OpcodeIf && !ifMissingElse && bl.elseAt > 0 {
  1487  				ctx = OpcodeElseName
  1488  			} else if bl.op != 0 {
  1489  				ctx = InstructionName(bl.op)
  1490  			}
  1491  
  1492  			// Check return types match
  1493  			if err := valueTypeStack.requireStackValues(false, ctx, bl.blockType.Results, true); err != nil {
  1494  				return err
  1495  			}
  1496  
  1497  			// Put the result types at the end after resetting at the stack limit
  1498  			// since we might have Any type between the limit and the current top.
  1499  			valueTypeStack.resetAtStackLimit()
  1500  			for _, exp := range bl.blockType.Results {
  1501  				valueTypeStack.push(exp)
  1502  			}
  1503  			// We exit if/loop/block, so reset the constraints on the stack manipulation
  1504  			// on values previously pushed by outer blocks.
  1505  			valueTypeStack.popStackLimit()
  1506  		} else if op == OpcodeReturn {
  1507  			// Same formatting as OpcodeEnd on the outer-most block
  1508  			if err := valueTypeStack.requireStackValues(false, "", functionType.Results, false); err != nil {
  1509  				return err
  1510  			}
  1511  			// return instruction is stack-polymorphic.
  1512  			valueTypeStack.unreachable()
  1513  		} else if op == OpcodeDrop {
  1514  			_, err := valueTypeStack.pop()
  1515  			if err != nil {
  1516  				return fmt.Errorf("invalid drop: %v", err)
  1517  			}
  1518  		} else if op == OpcodeSelect || op == OpcodeTypedSelect {
  1519  			if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
  1520  				return fmt.Errorf("type mismatch on 3rd select operand: %v", err)
  1521  			}
  1522  			v1, err := valueTypeStack.pop()
  1523  			if err != nil {
  1524  				return fmt.Errorf("invalid select: %v", err)
  1525  			}
  1526  			v2, err := valueTypeStack.pop()
  1527  			if err != nil {
  1528  				return fmt.Errorf("invalid select: %v", err)
  1529  			}
  1530  
  1531  			if op == OpcodeTypedSelect {
  1532  				if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
  1533  					return fmt.Errorf("%s is invalid as %w", InstructionName(op), err)
  1534  				}
  1535  				pc++
  1536  				if numTypeImmeidates := body[pc]; numTypeImmeidates != 1 {
  1537  					return fmt.Errorf("too many type immediates for %s", InstructionName(op))
  1538  				}
  1539  				pc++
  1540  				tp := body[pc]
  1541  				if tp != ValueTypeI32 && tp != ValueTypeI64 && tp != ValueTypeF32 && tp != ValueTypeF64 &&
  1542  					tp != api.ValueTypeExternref && tp != ValueTypeFuncref && tp != ValueTypeV128 {
  1543  					return fmt.Errorf("invalid type %s for %s", ValueTypeName(tp), OpcodeTypedSelectName)
  1544  				}
  1545  			} else if isReferenceValueType(v1) || isReferenceValueType(v2) {
  1546  				return fmt.Errorf("reference types cannot be used for non typed select instruction")
  1547  			}
  1548  
  1549  			if v1 != v2 && v1 != valueTypeUnknown && v2 != valueTypeUnknown {
  1550  				return fmt.Errorf("type mismatch on 1st and 2nd select operands")
  1551  			}
  1552  			if v1 == valueTypeUnknown {
  1553  				valueTypeStack.push(v2)
  1554  			} else {
  1555  				valueTypeStack.push(v1)
  1556  			}
  1557  		} else if op == OpcodeUnreachable {
  1558  			// unreachable instruction is stack-polymorphic.
  1559  			valueTypeStack.unreachable()
  1560  		} else if op == OpcodeNop {
  1561  		} else {
  1562  			return fmt.Errorf("invalid instruction 0x%x", op)
  1563  		}
  1564  	}
  1565  
  1566  	if len(controlBlockStack) > 0 {
  1567  		return fmt.Errorf("ill-nested block exists")
  1568  	}
  1569  	if valueTypeStack.maximumStackPointer > maxStackValues {
  1570  		return fmt.Errorf("function may have %d stack values, which exceeds limit %d", valueTypeStack.maximumStackPointer, maxStackValues)
  1571  	}
  1572  	return nil
  1573  }
  1574  
  1575  var vecExtractLanes = [...]struct {
  1576  	laneCeil   byte
  1577  	resultType ValueType
  1578  }{
  1579  	OpcodeVecI8x16ExtractLaneS: {laneCeil: 16, resultType: ValueTypeI32},
  1580  	OpcodeVecI8x16ExtractLaneU: {laneCeil: 16, resultType: ValueTypeI32},
  1581  	OpcodeVecI16x8ExtractLaneS: {laneCeil: 8, resultType: ValueTypeI32},
  1582  	OpcodeVecI16x8ExtractLaneU: {laneCeil: 8, resultType: ValueTypeI32},
  1583  	OpcodeVecI32x4ExtractLane:  {laneCeil: 4, resultType: ValueTypeI32},
  1584  	OpcodeVecI64x2ExtractLane:  {laneCeil: 2, resultType: ValueTypeI64},
  1585  	OpcodeVecF32x4ExtractLane:  {laneCeil: 4, resultType: ValueTypeF32},
  1586  	OpcodeVecF64x2ExtractLane:  {laneCeil: 2, resultType: ValueTypeF64},
  1587  }
  1588  
  1589  var vecReplaceLanes = [...]struct {
  1590  	laneCeil  byte
  1591  	paramType ValueType
  1592  }{
  1593  	OpcodeVecI8x16ReplaceLane: {laneCeil: 16, paramType: ValueTypeI32},
  1594  	OpcodeVecI16x8ReplaceLane: {laneCeil: 8, paramType: ValueTypeI32},
  1595  	OpcodeVecI32x4ReplaceLane: {laneCeil: 4, paramType: ValueTypeI32},
  1596  	OpcodeVecI64x2ReplaceLane: {laneCeil: 2, paramType: ValueTypeI64},
  1597  	OpcodeVecF32x4ReplaceLane: {laneCeil: 4, paramType: ValueTypeF32},
  1598  	OpcodeVecF64x2ReplaceLane: {laneCeil: 2, paramType: ValueTypeF64},
  1599  }
  1600  
  1601  var vecStoreLanes = [...]struct {
  1602  	alignMax uint32
  1603  	laneCeil byte
  1604  }{
  1605  	OpcodeVecV128Store64Lane: {alignMax: 64 / 8, laneCeil: 128 / 64},
  1606  	OpcodeVecV128Store32Lane: {alignMax: 32 / 8, laneCeil: 128 / 32},
  1607  	OpcodeVecV128Store16Lane: {alignMax: 16 / 8, laneCeil: 128 / 16},
  1608  	OpcodeVecV128Store8Lane:  {alignMax: 1, laneCeil: 128 / 8},
  1609  }
  1610  
  1611  var vecLoadLanes = [...]struct {
  1612  	alignMax uint32
  1613  	laneCeil byte
  1614  }{
  1615  	OpcodeVecV128Load64Lane: {alignMax: 64 / 8, laneCeil: 128 / 64},
  1616  	OpcodeVecV128Load32Lane: {alignMax: 32 / 8, laneCeil: 128 / 32},
  1617  	OpcodeVecV128Load16Lane: {alignMax: 16 / 8, laneCeil: 128 / 16},
  1618  	OpcodeVecV128Load8Lane:  {alignMax: 1, laneCeil: 128 / 8},
  1619  }
  1620  
  1621  var vecSplatValueTypes = [...]ValueType{
  1622  	OpcodeVecI8x16Splat: ValueTypeI32,
  1623  	OpcodeVecI16x8Splat: ValueTypeI32,
  1624  	OpcodeVecI32x4Splat: ValueTypeI32,
  1625  	OpcodeVecI64x2Splat: ValueTypeI64,
  1626  	OpcodeVecF32x4Splat: ValueTypeF32,
  1627  	OpcodeVecF64x2Splat: ValueTypeF64,
  1628  }
  1629  
  1630  type valueTypeStack struct {
  1631  	stack               []ValueType
  1632  	stackLimits         []int
  1633  	maximumStackPointer int
  1634  }
  1635  
  1636  const (
  1637  	// Only used in the analyzeFunction below.
  1638  	valueTypeUnknown = ValueType(0xFF)
  1639  )
  1640  
  1641  func (s *valueTypeStack) tryPop() (vt ValueType, limit int, ok bool) {
  1642  	if len(s.stackLimits) > 0 {
  1643  		limit = s.stackLimits[len(s.stackLimits)-1]
  1644  	}
  1645  	stackLen := len(s.stack)
  1646  	if stackLen <= limit {
  1647  		return
  1648  	} else if stackLen == limit+1 && s.stack[limit] == valueTypeUnknown {
  1649  		vt = valueTypeUnknown
  1650  		ok = true
  1651  		return
  1652  	} else {
  1653  		vt = s.stack[stackLen-1]
  1654  		s.stack = s.stack[:stackLen-1]
  1655  		ok = true
  1656  		return
  1657  	}
  1658  }
  1659  
  1660  func (s *valueTypeStack) pop() (ValueType, error) {
  1661  	if vt, limit, ok := s.tryPop(); ok {
  1662  		return vt, nil
  1663  	} else {
  1664  		return 0, fmt.Errorf("invalid operation: trying to pop at %d with limit %d", len(s.stack), limit)
  1665  	}
  1666  }
  1667  
  1668  // popAndVerifyType returns an error if the stack value is unexpected.
  1669  func (s *valueTypeStack) popAndVerifyType(expected ValueType) error {
  1670  	have, _, ok := s.tryPop()
  1671  	if !ok {
  1672  		return fmt.Errorf("%s missing", ValueTypeName(expected))
  1673  	}
  1674  	if have != expected && have != valueTypeUnknown && expected != valueTypeUnknown {
  1675  		return fmt.Errorf("type mismatch: expected %s, but was %s", ValueTypeName(expected), ValueTypeName(have))
  1676  	}
  1677  	return nil
  1678  }
  1679  
  1680  func (s *valueTypeStack) push(v ValueType) {
  1681  	s.stack = append(s.stack, v)
  1682  	if sp := len(s.stack); sp > s.maximumStackPointer {
  1683  		s.maximumStackPointer = sp
  1684  	}
  1685  }
  1686  
  1687  func (s *valueTypeStack) unreachable() {
  1688  	s.resetAtStackLimit()
  1689  	s.stack = append(s.stack, valueTypeUnknown)
  1690  }
  1691  
  1692  func (s *valueTypeStack) resetAtStackLimit() {
  1693  	if len(s.stackLimits) != 0 {
  1694  		s.stack = s.stack[:s.stackLimits[len(s.stackLimits)-1]]
  1695  	} else {
  1696  		s.stack = []ValueType{}
  1697  	}
  1698  }
  1699  
  1700  func (s *valueTypeStack) popStackLimit() {
  1701  	if len(s.stackLimits) != 0 {
  1702  		s.stackLimits = s.stackLimits[:len(s.stackLimits)-1]
  1703  	}
  1704  }
  1705  
  1706  // pushStackLimit pushes the control frame's bottom of the stack.
  1707  func (s *valueTypeStack) pushStackLimit(params int) {
  1708  	limit := len(s.stack) - params
  1709  	s.stackLimits = append(s.stackLimits, limit)
  1710  }
  1711  
  1712  func (s *valueTypeStack) popParams(oc Opcode, want []ValueType, checkAboveLimit bool) error {
  1713  	return s.requireStackValues(true, InstructionName(oc), want, checkAboveLimit)
  1714  }
  1715  
  1716  func (s *valueTypeStack) popResults(oc Opcode, want []ValueType, checkAboveLimit bool) error {
  1717  	return s.requireStackValues(false, InstructionName(oc), want, checkAboveLimit)
  1718  }
  1719  
  1720  func (s *valueTypeStack) requireStackValues(
  1721  	isParam bool,
  1722  	context string,
  1723  	want []ValueType,
  1724  	checkAboveLimit bool,
  1725  ) error {
  1726  	limit := 0
  1727  	if len(s.stackLimits) > 0 {
  1728  		limit = s.stackLimits[len(s.stackLimits)-1]
  1729  	}
  1730  	// Iterate backwards as we are comparing the desired slice against stack value types.
  1731  	countWanted := len(want)
  1732  
  1733  	// First, check if there are enough values on the stack.
  1734  	have := make([]ValueType, 0, countWanted)
  1735  	for i := countWanted - 1; i >= 0; i-- {
  1736  		popped, _, ok := s.tryPop()
  1737  		if !ok {
  1738  			if len(have) > len(want) {
  1739  				return typeCountError(isParam, context, have, want)
  1740  			}
  1741  			return typeCountError(isParam, context, have, want)
  1742  		}
  1743  		have = append(have, popped)
  1744  	}
  1745  
  1746  	// Now, check if there are too many values.
  1747  	if checkAboveLimit {
  1748  		if !(limit == len(s.stack) || (limit+1 == len(s.stack) && s.stack[limit] == valueTypeUnknown)) {
  1749  			return typeCountError(isParam, context, append(s.stack, want...), want)
  1750  		}
  1751  	}
  1752  
  1753  	// Finally, check the types of the values:
  1754  	for i, v := range have {
  1755  		nextWant := want[countWanted-i-1] // have is in reverse order (stack)
  1756  		if v != nextWant && v != valueTypeUnknown && nextWant != valueTypeUnknown {
  1757  			return typeMismatchError(isParam, context, v, nextWant, i)
  1758  		}
  1759  	}
  1760  	return nil
  1761  }
  1762  
  1763  // typeMismatchError returns an error similar to go compiler's error on type mismatch.
  1764  func typeMismatchError(isParam bool, context string, have ValueType, want ValueType, i int) error {
  1765  	var ret strings.Builder
  1766  	ret.WriteString("cannot use ")
  1767  	ret.WriteString(ValueTypeName(have))
  1768  	if context != "" {
  1769  		ret.WriteString(" in ")
  1770  		ret.WriteString(context)
  1771  		ret.WriteString(" block")
  1772  	}
  1773  	if isParam {
  1774  		ret.WriteString(" as param")
  1775  	} else {
  1776  		ret.WriteString(" as result")
  1777  	}
  1778  	ret.WriteString("[")
  1779  	ret.WriteString(strconv.Itoa(i))
  1780  	ret.WriteString("] type ")
  1781  	ret.WriteString(ValueTypeName(want))
  1782  	return errors.New(ret.String())
  1783  }
  1784  
  1785  // typeCountError returns an error similar to go compiler's error on type count mismatch.
  1786  func typeCountError(isParam bool, context string, have []ValueType, want []ValueType) error {
  1787  	var ret strings.Builder
  1788  	if len(have) > len(want) {
  1789  		ret.WriteString("too many ")
  1790  	} else {
  1791  		ret.WriteString("not enough ")
  1792  	}
  1793  	if isParam {
  1794  		ret.WriteString("params")
  1795  	} else {
  1796  		ret.WriteString("results")
  1797  	}
  1798  	if context != "" {
  1799  		if isParam {
  1800  			ret.WriteString(" for ")
  1801  		} else {
  1802  			ret.WriteString(" in ")
  1803  		}
  1804  		ret.WriteString(context)
  1805  		ret.WriteString(" block")
  1806  	}
  1807  	ret.WriteString("\n\thave (")
  1808  	writeValueTypes(have, &ret)
  1809  	ret.WriteString(")\n\twant (")
  1810  	writeValueTypes(want, &ret)
  1811  	ret.WriteByte(')')
  1812  	return errors.New(ret.String())
  1813  }
  1814  
  1815  func writeValueTypes(vts []ValueType, ret *strings.Builder) {
  1816  	switch len(vts) {
  1817  	case 0:
  1818  	case 1:
  1819  		ret.WriteString(ValueTypeName(vts[0]))
  1820  	default:
  1821  		ret.WriteString(ValueTypeName(vts[0]))
  1822  		for _, vt := range vts[1:] {
  1823  			ret.WriteString(", ")
  1824  			ret.WriteString(ValueTypeName(vt))
  1825  		}
  1826  	}
  1827  }
  1828  
  1829  func (s *valueTypeStack) String() string {
  1830  	var typeStrs, limits []string
  1831  	for _, v := range s.stack {
  1832  		var str string
  1833  		if v == valueTypeUnknown {
  1834  			str = "unknown"
  1835  		} else {
  1836  			str = ValueTypeName(v)
  1837  		}
  1838  		typeStrs = append(typeStrs, str)
  1839  	}
  1840  	for _, d := range s.stackLimits {
  1841  		limits = append(limits, fmt.Sprintf("%d", d))
  1842  	}
  1843  	return fmt.Sprintf("{stack: [%s], limits: [%s]}",
  1844  		strings.Join(typeStrs, ", "), strings.Join(limits, ","))
  1845  }
  1846  
  1847  type controlBlock struct {
  1848  	startAt, elseAt, endAt uint64
  1849  	blockType              *FunctionType
  1850  	blockTypeBytes         uint64
  1851  	// op is zero when the outermost block
  1852  	op Opcode
  1853  }
  1854  
  1855  // DecodeBlockType decodes the type index from a positive 33-bit signed integer. Negative numbers indicate up to one
  1856  // WebAssembly 1.0 (20191205) compatible result type. Positive numbers are decoded when `enabledFeatures` include
  1857  // CoreFeatureMultiValue and include an index in the Module.TypeSection.
  1858  //
  1859  // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-blocktype
  1860  // See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/multi-value/Overview.md
  1861  func DecodeBlockType(types []*FunctionType, r *bytes.Reader, enabledFeatures api.CoreFeatures) (*FunctionType, uint64, error) {
  1862  	raw, num, err := leb128.DecodeInt33AsInt64(r)
  1863  	if err != nil {
  1864  		return nil, 0, fmt.Errorf("decode int33: %w", err)
  1865  	}
  1866  
  1867  	var ret *FunctionType
  1868  	switch raw {
  1869  	case -64: // 0x40 in original byte = nil
  1870  		ret = &FunctionType{}
  1871  	case -1: // 0x7f in original byte = i32
  1872  		ret = &FunctionType{Results: []ValueType{ValueTypeI32}, ResultNumInUint64: 1}
  1873  	case -2: // 0x7e in original byte = i64
  1874  		ret = &FunctionType{Results: []ValueType{ValueTypeI64}, ResultNumInUint64: 1}
  1875  	case -3: // 0x7d in original byte = f32
  1876  		ret = &FunctionType{Results: []ValueType{ValueTypeF32}, ResultNumInUint64: 1}
  1877  	case -4: // 0x7c in original byte = f64
  1878  		ret = &FunctionType{Results: []ValueType{ValueTypeF64}, ResultNumInUint64: 1}
  1879  	case -5: // 0x7b in original byte = v128
  1880  		ret = &FunctionType{Results: []ValueType{ValueTypeV128}, ResultNumInUint64: 2}
  1881  	case -16: // 0x70 in original byte = funcref
  1882  		ret = &FunctionType{Results: []ValueType{ValueTypeFuncref}, ResultNumInUint64: 1}
  1883  	case -17: // 0x6f in original byte = externref
  1884  		ret = &FunctionType{Results: []ValueType{ValueTypeExternref}, ResultNumInUint64: 1}
  1885  	default:
  1886  		if err = enabledFeatures.RequireEnabled(api.CoreFeatureMultiValue); err != nil {
  1887  			return nil, num, fmt.Errorf("block with function type return invalid as %v", err)
  1888  		}
  1889  		if raw < 0 || (raw >= int64(len(types))) {
  1890  			return nil, 0, fmt.Errorf("type index out of range: %d", raw)
  1891  		}
  1892  		ret = types[raw]
  1893  	}
  1894  	return ret, num, err
  1895  }