...

Source file src/github.com/tetratelabs/wazero/internal/wasm/func_validation.go

Documentation: github.com/tetratelabs/wazero/internal/wasm

     1  package wasm
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  	"strconv"
     8  	"strings"
     9  
    10  	"github.com/tetratelabs/wazero/api"
    11  	"github.com/tetratelabs/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, which is prefixed by imports. The value is the TypeSection index.
    22  // * globals are the global index, 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(sts *stacks, enabledFeatures api.CoreFeatures, idx Index, functions []Index,
    30  	globals []GlobalType, memory *Memory, tables []Table, declaredFunctionIndexes map[Index]struct{}, br *bytes.Reader,
    31  ) error {
    32  	return m.validateFunctionWithMaxStackValues(sts, enabledFeatures, idx, functions, globals, memory, tables, maximumValuesOnStack, declaredFunctionIndexes, br)
    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  // * stacks is to track the state of Wasm value and control frame stacks at anypoint of execution, and reused to reduce allocation.
    56  // * maxStackValues is the maximum height of values stack which the target is allowed to reach.
    57  func (m *Module) validateFunctionWithMaxStackValues(
    58  	sts *stacks,
    59  	enabledFeatures api.CoreFeatures,
    60  	idx Index,
    61  	functions []Index,
    62  	globals []GlobalType,
    63  	memory *Memory,
    64  	tables []Table,
    65  	maxStackValues int,
    66  	declaredFunctionIndexes map[Index]struct{},
    67  	br *bytes.Reader,
    68  ) error {
    69  	functionType := &m.TypeSection[m.FunctionSection[idx]]
    70  	code := &m.CodeSection[idx]
    71  	body := code.Body
    72  	localTypes := code.LocalTypes
    73  
    74  	sts.reset(functionType)
    75  	valueTypeStack := &sts.vs
    76  	// We start with the outermost control block which is for function return if the code branches into it.
    77  	controlBlockStack := &sts.cs
    78  
    79  	// Now start walking through all the instructions in the body while tracking
    80  	// control blocks and value types to check the validity of all instructions.
    81  	for pc := uint64(0); pc < uint64(len(body)); pc++ {
    82  		op := body[pc]
    83  		if false {
    84  			var instName string
    85  			if op == OpcodeMiscPrefix {
    86  				instName = MiscInstructionName(body[pc+1])
    87  			} else if op == OpcodeVecPrefix {
    88  				instName = VectorInstructionName(body[pc+1])
    89  			} else {
    90  				instName = InstructionName(op)
    91  			}
    92  			fmt.Printf("handling %s, stack=%s, blocks: %v\n", instName, valueTypeStack.stack, controlBlockStack)
    93  		}
    94  
    95  		if OpcodeI32Load <= op && op <= OpcodeI64Store32 {
    96  			if memory == nil {
    97  				return fmt.Errorf("memory must exist for %s", InstructionName(op))
    98  			}
    99  			pc++
   100  			align, _, read, err := readMemArg(pc, body)
   101  			if err != nil {
   102  				return err
   103  			}
   104  			pc += read - 1
   105  			switch op {
   106  			case OpcodeI32Load:
   107  				if 1<<align > 32/8 {
   108  					return fmt.Errorf("invalid memory alignment")
   109  				}
   110  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   111  					return err
   112  				}
   113  				valueTypeStack.push(ValueTypeI32)
   114  			case OpcodeF32Load:
   115  				if 1<<align > 32/8 {
   116  					return fmt.Errorf("invalid memory alignment")
   117  				}
   118  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   119  					return err
   120  				}
   121  				valueTypeStack.push(ValueTypeF32)
   122  			case OpcodeI32Store:
   123  				if 1<<align > 32/8 {
   124  					return fmt.Errorf("invalid memory alignment")
   125  				}
   126  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   127  					return err
   128  				}
   129  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   130  					return err
   131  				}
   132  			case OpcodeF32Store:
   133  				if 1<<align > 32/8 {
   134  					return fmt.Errorf("invalid memory alignment")
   135  				}
   136  				if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
   137  					return err
   138  				}
   139  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   140  					return err
   141  				}
   142  			case OpcodeI64Load:
   143  				if 1<<align > 64/8 {
   144  					return fmt.Errorf("invalid memory alignment")
   145  				}
   146  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   147  					return err
   148  				}
   149  				valueTypeStack.push(ValueTypeI64)
   150  			case OpcodeF64Load:
   151  				if 1<<align > 64/8 {
   152  					return fmt.Errorf("invalid memory alignment")
   153  				}
   154  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   155  					return err
   156  				}
   157  				valueTypeStack.push(ValueTypeF64)
   158  			case OpcodeI64Store:
   159  				if 1<<align > 64/8 {
   160  					return fmt.Errorf("invalid memory alignment")
   161  				}
   162  				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
   163  					return err
   164  				}
   165  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   166  					return err
   167  				}
   168  			case OpcodeF64Store:
   169  				if 1<<align > 64/8 {
   170  					return fmt.Errorf("invalid memory alignment")
   171  				}
   172  				if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
   173  					return err
   174  				}
   175  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   176  					return err
   177  				}
   178  			case OpcodeI32Load8S:
   179  				if 1<<align > 1 {
   180  					return fmt.Errorf("invalid memory alignment")
   181  				}
   182  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   183  					return err
   184  				}
   185  				valueTypeStack.push(ValueTypeI32)
   186  			case OpcodeI32Load8U:
   187  				if 1<<align > 1 {
   188  					return fmt.Errorf("invalid memory alignment")
   189  				}
   190  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   191  					return err
   192  				}
   193  				valueTypeStack.push(ValueTypeI32)
   194  			case OpcodeI64Load8S, OpcodeI64Load8U:
   195  				if 1<<align > 1 {
   196  					return fmt.Errorf("invalid memory alignment")
   197  				}
   198  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   199  					return err
   200  				}
   201  				valueTypeStack.push(ValueTypeI64)
   202  			case OpcodeI32Store8:
   203  				if 1<<align > 1 {
   204  					return fmt.Errorf("invalid memory alignment")
   205  				}
   206  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   207  					return err
   208  				}
   209  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   210  					return err
   211  				}
   212  			case OpcodeI64Store8:
   213  				if 1<<align > 1 {
   214  					return fmt.Errorf("invalid memory alignment")
   215  				}
   216  				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
   217  					return err
   218  				}
   219  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   220  					return err
   221  				}
   222  			case OpcodeI32Load16S, OpcodeI32Load16U:
   223  				if 1<<align > 16/8 {
   224  					return fmt.Errorf("invalid memory alignment")
   225  				}
   226  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   227  					return err
   228  				}
   229  				valueTypeStack.push(ValueTypeI32)
   230  			case OpcodeI64Load16S, OpcodeI64Load16U:
   231  				if 1<<align > 16/8 {
   232  					return fmt.Errorf("invalid memory alignment")
   233  				}
   234  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   235  					return err
   236  				}
   237  				valueTypeStack.push(ValueTypeI64)
   238  			case OpcodeI32Store16:
   239  				if 1<<align > 16/8 {
   240  					return fmt.Errorf("invalid memory alignment")
   241  				}
   242  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   243  					return err
   244  				}
   245  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   246  					return err
   247  				}
   248  			case OpcodeI64Store16:
   249  				if 1<<align > 16/8 {
   250  					return fmt.Errorf("invalid memory alignment")
   251  				}
   252  				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
   253  					return err
   254  				}
   255  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   256  					return err
   257  				}
   258  			case OpcodeI64Load32S, OpcodeI64Load32U:
   259  				if 1<<align > 32/8 {
   260  					return fmt.Errorf("invalid memory alignment")
   261  				}
   262  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   263  					return err
   264  				}
   265  				valueTypeStack.push(ValueTypeI64)
   266  			case OpcodeI64Store32:
   267  				if 1<<align > 32/8 {
   268  					return fmt.Errorf("invalid memory alignment")
   269  				}
   270  				if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
   271  					return err
   272  				}
   273  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   274  					return err
   275  				}
   276  			}
   277  		} else if OpcodeMemorySize <= op && op <= OpcodeMemoryGrow {
   278  			if memory == nil {
   279  				return fmt.Errorf("memory must exist for %s", InstructionName(op))
   280  			}
   281  			pc++
   282  			val, num, err := leb128.LoadUint32(body[pc:])
   283  			if err != nil {
   284  				return fmt.Errorf("read immediate: %v", err)
   285  			}
   286  			if val != 0 || num != 1 {
   287  				return fmt.Errorf("memory instruction reserved bytes not zero with 1 byte")
   288  			}
   289  			switch Opcode(op) {
   290  			case OpcodeMemoryGrow:
   291  				if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   292  					return err
   293  				}
   294  				valueTypeStack.push(ValueTypeI32)
   295  			case OpcodeMemorySize:
   296  				valueTypeStack.push(ValueTypeI32)
   297  			}
   298  			pc += num - 1
   299  		} else if OpcodeI32Const <= op && op <= OpcodeF64Const {
   300  			pc++
   301  			switch Opcode(op) {
   302  			case OpcodeI32Const:
   303  				_, num, err := leb128.LoadInt32(body[pc:])
   304  				if err != nil {
   305  					return fmt.Errorf("read i32 immediate: %s", err)
   306  				}
   307  				pc += num - 1
   308  				valueTypeStack.push(ValueTypeI32)
   309  			case OpcodeI64Const:
   310  				_, num, err := leb128.LoadInt64(body[pc:])
   311  				if err != nil {
   312  					return fmt.Errorf("read i64 immediate: %v", err)
   313  				}
   314  				valueTypeStack.push(ValueTypeI64)
   315  				pc += num - 1
   316  			case OpcodeF32Const:
   317  				valueTypeStack.push(ValueTypeF32)
   318  				pc += 3
   319  			case OpcodeF64Const:
   320  				valueTypeStack.push(ValueTypeF64)
   321  				pc += 7
   322  			}
   323  		} else if OpcodeLocalGet <= op && op <= OpcodeGlobalSet {
   324  			pc++
   325  			index, num, err := leb128.LoadUint32(body[pc:])
   326  			if err != nil {
   327  				return fmt.Errorf("read immediate: %v", err)
   328  			}
   329  			pc += num - 1
   330  			switch op {
   331  			case OpcodeLocalGet:
   332  				inputLen := uint32(len(functionType.Params))
   333  				if l := uint32(len(localTypes)) + inputLen; index >= l {
   334  					return fmt.Errorf("invalid local index for %s %d >= %d(=len(locals)+len(parameters))",
   335  						OpcodeLocalGetName, index, l)
   336  				}
   337  				if index < inputLen {
   338  					valueTypeStack.push(functionType.Params[index])
   339  				} else {
   340  					valueTypeStack.push(localTypes[index-inputLen])
   341  				}
   342  			case OpcodeLocalSet:
   343  				inputLen := uint32(len(functionType.Params))
   344  				if l := uint32(len(localTypes)) + inputLen; index >= l {
   345  					return fmt.Errorf("invalid local index for %s %d >= %d(=len(locals)+len(parameters))",
   346  						OpcodeLocalSetName, index, l)
   347  				}
   348  				var expType ValueType
   349  				if index < inputLen {
   350  					expType = functionType.Params[index]
   351  				} else {
   352  					expType = localTypes[index-inputLen]
   353  				}
   354  				if err := valueTypeStack.popAndVerifyType(expType); err != nil {
   355  					return err
   356  				}
   357  			case OpcodeLocalTee:
   358  				inputLen := uint32(len(functionType.Params))
   359  				if l := uint32(len(localTypes)) + inputLen; index >= l {
   360  					return fmt.Errorf("invalid local index for %s %d >= %d(=len(locals)+len(parameters))",
   361  						OpcodeLocalTeeName, index, l)
   362  				}
   363  				var expType ValueType
   364  				if index < inputLen {
   365  					expType = functionType.Params[index]
   366  				} else {
   367  					expType = localTypes[index-inputLen]
   368  				}
   369  				if err := valueTypeStack.popAndVerifyType(expType); err != nil {
   370  					return err
   371  				}
   372  				valueTypeStack.push(expType)
   373  			case OpcodeGlobalGet:
   374  				if index >= uint32(len(globals)) {
   375  					return fmt.Errorf("invalid index for %s", OpcodeGlobalGetName)
   376  				}
   377  				valueTypeStack.push(globals[index].ValType)
   378  			case OpcodeGlobalSet:
   379  				if index >= uint32(len(globals)) {
   380  					return fmt.Errorf("invalid global index")
   381  				} else if !globals[index].Mutable {
   382  					return fmt.Errorf("%s when not mutable", OpcodeGlobalSetName)
   383  				} else if err := valueTypeStack.popAndVerifyType(
   384  					globals[index].ValType); err != nil {
   385  					return err
   386  				}
   387  			}
   388  		} else if op == OpcodeBr {
   389  			pc++
   390  			index, num, err := leb128.LoadUint32(body[pc:])
   391  			if err != nil {
   392  				return fmt.Errorf("read immediate: %v", err)
   393  			} else if int(index) >= len(controlBlockStack.stack) {
   394  				return fmt.Errorf("invalid %s operation: index out of range", OpcodeBrName)
   395  			}
   396  			pc += num - 1
   397  			// Check type soundness.
   398  			target := &controlBlockStack.stack[len(controlBlockStack.stack)-int(index)-1]
   399  			var targetResultType []ValueType
   400  			if target.op == OpcodeLoop {
   401  				targetResultType = target.blockType.Params
   402  			} else {
   403  				targetResultType = target.blockType.Results
   404  			}
   405  			if err = valueTypeStack.popResults(op, targetResultType, false); err != nil {
   406  				return err
   407  			}
   408  			// br instruction is stack-polymorphic.
   409  			valueTypeStack.unreachable()
   410  		} else if op == OpcodeBrIf {
   411  			pc++
   412  			index, num, err := leb128.LoadUint32(body[pc:])
   413  			if err != nil {
   414  				return fmt.Errorf("read immediate: %v", err)
   415  			} else if int(index) >= len(controlBlockStack.stack) {
   416  				return fmt.Errorf(
   417  					"invalid ln param given for %s: index=%d with %d for the current label stack length",
   418  					OpcodeBrIfName, index, len(controlBlockStack.stack))
   419  			}
   420  			pc += num - 1
   421  			if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   422  				return fmt.Errorf("cannot pop the required operand for %s", OpcodeBrIfName)
   423  			}
   424  			// Check type soundness.
   425  			target := &controlBlockStack.stack[len(controlBlockStack.stack)-int(index)-1]
   426  			var targetResultType []ValueType
   427  			if target.op == OpcodeLoop {
   428  				targetResultType = target.blockType.Params
   429  			} else {
   430  				targetResultType = target.blockType.Results
   431  			}
   432  			if err := valueTypeStack.popResults(op, targetResultType, false); err != nil {
   433  				return err
   434  			}
   435  			// Push back the result
   436  			for _, t := range targetResultType {
   437  				valueTypeStack.push(t)
   438  			}
   439  		} else if op == OpcodeBrTable {
   440  			pc++
   441  			br.Reset(body[pc:])
   442  			nl, num, err := leb128.DecodeUint32(br)
   443  			if err != nil {
   444  				return fmt.Errorf("read immediate: %w", err)
   445  			}
   446  
   447  			list := make([]uint32, nl)
   448  			for i := uint32(0); i < nl; i++ {
   449  				l, n, err := leb128.DecodeUint32(br)
   450  				if err != nil {
   451  					return fmt.Errorf("read immediate: %w", err)
   452  				}
   453  				num += n
   454  				list[i] = l
   455  			}
   456  			ln, n, err := leb128.DecodeUint32(br)
   457  			if err != nil {
   458  				return fmt.Errorf("read immediate: %w", err)
   459  			} else if int(ln) >= len(controlBlockStack.stack) {
   460  				return fmt.Errorf(
   461  					"invalid ln param given for %s: ln=%d with %d for the current label stack length",
   462  					OpcodeBrTableName, ln, len(controlBlockStack.stack))
   463  			}
   464  			pc += n + num - 1
   465  			// Check type soundness.
   466  			if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
   467  				return fmt.Errorf("cannot pop the required operand for %s", OpcodeBrTableName)
   468  			}
   469  			lnLabel := &controlBlockStack.stack[len(controlBlockStack.stack)-1-int(ln)]
   470  			var defaultLabelType []ValueType
   471  			// Below, we might modify the slice in case of unreachable. Therefore,
   472  			// we have to copy the content of block result types, otherwise the original
   473  			// function type might result in invalid value types if the block is the outermost label
   474  			// which equals the function's type.
   475  			if lnLabel.op != OpcodeLoop { // Loop operation doesn't require results since the continuation is the beginning of the loop.
   476  				defaultLabelType = make([]ValueType, len(lnLabel.blockType.Results))
   477  				copy(defaultLabelType, lnLabel.blockType.Results)
   478  			} else {
   479  				defaultLabelType = make([]ValueType, len(lnLabel.blockType.Params))
   480  				copy(defaultLabelType, lnLabel.blockType.Params)
   481  			}
   482  
   483  			if enabledFeatures.IsEnabled(api.CoreFeatureReferenceTypes) {
   484  				// As of reference-types proposal, br_table on unreachable state
   485  				// can choose unknown types for expected parameter types for each label.
   486  				// https://github.com/WebAssembly/reference-types/pull/116
   487  				for i := range defaultLabelType {
   488  					index := len(defaultLabelType) - 1 - i
   489  					exp := defaultLabelType[index]
   490  					actual, err := valueTypeStack.pop()
   491  					if err != nil {
   492  						return err
   493  					}
   494  					if actual == valueTypeUnknown {
   495  						// Re-assign the expected type to unknown.
   496  						defaultLabelType[index] = valueTypeUnknown
   497  					} else if actual != exp {
   498  						return typeMismatchError(true, OpcodeBrTableName, actual, exp, i)
   499  					}
   500  				}
   501  			} else {
   502  				if err = valueTypeStack.popResults(op, defaultLabelType, false); err != nil {
   503  					return err
   504  				}
   505  			}
   506  
   507  			for _, l := range list {
   508  				if int(l) >= len(controlBlockStack.stack) {
   509  					return fmt.Errorf("invalid l param given for %s", OpcodeBrTableName)
   510  				}
   511  				label := &controlBlockStack.stack[len(controlBlockStack.stack)-1-int(l)]
   512  				var tableLabelType []ValueType
   513  				if label.op != OpcodeLoop {
   514  					tableLabelType = label.blockType.Results
   515  				} else {
   516  					tableLabelType = label.blockType.Params
   517  				}
   518  				if len(defaultLabelType) != len(tableLabelType) {
   519  					return fmt.Errorf("inconsistent block type length for %s at %d; %v (ln=%d) != %v (l=%d)", OpcodeBrTableName, l, defaultLabelType, ln, tableLabelType, l)
   520  				}
   521  				for i := range defaultLabelType {
   522  					if defaultLabelType[i] != valueTypeUnknown && defaultLabelType[i] != tableLabelType[i] {
   523  						return fmt.Errorf("incosistent block type for %s at %d", OpcodeBrTableName, l)
   524  					}
   525  				}
   526  			}
   527  
   528  			// br_table instruction is stack-polymorphic.
   529  			valueTypeStack.unreachable()
   530  		} else if op == OpcodeCall {
   531  			pc++
   532  			index, num, err := leb128.LoadUint32(body[pc:])
   533  			if err != nil {
   534  				return fmt.Errorf("read immediate: %v", err)
   535  			}
   536  			pc += num - 1
   537  			if int(index) >= len(functions) {
   538  				return fmt.Errorf("invalid function index")
   539  			}
   540  			funcType := &m.TypeSection[functions[index]]
   541  			for i := 0; i < len(funcType.Params); i++ {
   542  				if err := valueTypeStack.popAndVerifyType(funcType.Params[len(funcType.Params)-1-i]); err != nil {
   543  					return fmt.Errorf("type mismatch on %s operation param type: %v", OpcodeCallName, err)
   544  				}
   545  			}
   546  			for _, exp := range funcType.Results {
   547  				valueTypeStack.push(exp)
   548  			}
   549  		} else if op == OpcodeCallIndirect {
   550  			pc++
   551  			typeIndex, num, err := leb128.LoadUint32(body[pc:])
   552  			if err != nil {
   553  				return fmt.Errorf("read immediate: %v", err)
   554  			}
   555  			pc += num
   556  
   557  			if int(typeIndex) >= len(m.TypeSection) {
   558  				return fmt.Errorf("invalid type index at %s: %d", OpcodeCallIndirectName, typeIndex)
   559  			}
   560  
   561  			tableIndex, num, err := leb128.LoadUint32(body[pc:])
   562  			if err != nil {
   563  				return fmt.Errorf("read table index: %v", err)
   564  			}
   565  			pc += num - 1
   566  			if tableIndex != 0 {
   567  				if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
   568  					return fmt.Errorf("table index must be zero but was %d: %w", tableIndex, err)
   569  				}
   570  			}
   571  
   572  			if tableIndex >= uint32(len(tables)) {
   573  				return fmt.Errorf("unknown table index: %d", tableIndex)
   574  			}
   575  
   576  			table := tables[tableIndex]
   577  			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 := &m.TypeSection[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 {
  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 {
  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 {
  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 {
  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  			br.Reset(body[pc+1:])
  1393  			bt, num, err := DecodeBlockType(m.TypeSection, br, enabledFeatures)
  1394  			if err != nil {
  1395  				return fmt.Errorf("read block: %w", err)
  1396  			}
  1397  			controlBlockStack.push(pc, 0, 0, bt, num, 0)
  1398  			if err = valueTypeStack.popParams(op, bt.Params, false); err != nil {
  1399  				return err
  1400  			}
  1401  			// Plus we have to push any block params again.
  1402  			for _, p := range bt.Params {
  1403  				valueTypeStack.push(p)
  1404  			}
  1405  			valueTypeStack.pushStackLimit(len(bt.Params))
  1406  			pc += num
  1407  		} else if op == OpcodeLoop {
  1408  			br.Reset(body[pc+1:])
  1409  			bt, num, err := DecodeBlockType(m.TypeSection, br, enabledFeatures)
  1410  			if err != nil {
  1411  				return fmt.Errorf("read block: %w", err)
  1412  			}
  1413  			controlBlockStack.push(pc, 0, 0, bt, num, op)
  1414  			if err = valueTypeStack.popParams(op, bt.Params, false); err != nil {
  1415  				return err
  1416  			}
  1417  			// Plus we have to push any block params again.
  1418  			for _, p := range bt.Params {
  1419  				valueTypeStack.push(p)
  1420  			}
  1421  			valueTypeStack.pushStackLimit(len(bt.Params))
  1422  			pc += num
  1423  		} else if op == OpcodeIf {
  1424  			br.Reset(body[pc+1:])
  1425  			bt, num, err := DecodeBlockType(m.TypeSection, br, enabledFeatures)
  1426  			if err != nil {
  1427  				return fmt.Errorf("read block: %w", err)
  1428  			}
  1429  			controlBlockStack.push(pc, 0, 0, bt, num, op)
  1430  			if err = valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
  1431  				return fmt.Errorf("cannot pop the operand for 'if': %v", err)
  1432  			}
  1433  			if err = valueTypeStack.popParams(op, bt.Params, false); err != nil {
  1434  				return err
  1435  			}
  1436  			// Plus we have to push any block params again.
  1437  			for _, p := range bt.Params {
  1438  				valueTypeStack.push(p)
  1439  			}
  1440  			valueTypeStack.pushStackLimit(len(bt.Params))
  1441  			pc += num
  1442  		} else if op == OpcodeElse {
  1443  			if len(controlBlockStack.stack) == 0 {
  1444  				return fmt.Errorf("redundant Else instruction at %#x", pc)
  1445  			}
  1446  			bl := &controlBlockStack.stack[len(controlBlockStack.stack)-1]
  1447  			bl.elseAt = pc
  1448  			// Check the type soundness of the instructions *before* entering this else Op.
  1449  			if err := valueTypeStack.popResults(OpcodeIf, bl.blockType.Results, true); err != nil {
  1450  				return err
  1451  			}
  1452  			// Before entering instructions inside else, we pop all the values pushed by then block.
  1453  			valueTypeStack.resetAtStackLimit()
  1454  			// Plus we have to push any block params again.
  1455  			for _, p := range bl.blockType.Params {
  1456  				valueTypeStack.push(p)
  1457  			}
  1458  		} else if op == OpcodeEnd {
  1459  			if len(controlBlockStack.stack) == 0 {
  1460  				return fmt.Errorf("redundant End instruction at %#x", pc)
  1461  			}
  1462  			bl := controlBlockStack.pop()
  1463  			bl.endAt = pc
  1464  
  1465  			// OpcodeEnd can end a block or the function itself. Check to see what it is:
  1466  
  1467  			ifMissingElse := bl.op == OpcodeIf && bl.elseAt <= bl.startAt
  1468  			if ifMissingElse {
  1469  				// If this is the end of block without else, the number of block's results and params must be same.
  1470  				// Otherwise, the value stack would result in the inconsistent state at runtime.
  1471  				if !bytes.Equal(bl.blockType.Results, bl.blockType.Params) {
  1472  					return typeCountError(false, OpcodeElseName, bl.blockType.Params, bl.blockType.Results)
  1473  				}
  1474  				// -1 skips else, to handle if block without else properly.
  1475  				bl.elseAt = bl.endAt - 1
  1476  			}
  1477  
  1478  			// Determine the block context
  1479  			ctx := "" // the outer-most block: the function return
  1480  			if bl.op == OpcodeIf && !ifMissingElse && bl.elseAt > 0 {
  1481  				ctx = OpcodeElseName
  1482  			} else if bl.op != 0 {
  1483  				ctx = InstructionName(bl.op)
  1484  			}
  1485  
  1486  			// Check return types match
  1487  			if err := valueTypeStack.requireStackValues(false, ctx, bl.blockType.Results, true); err != nil {
  1488  				return err
  1489  			}
  1490  
  1491  			// Put the result types at the end after resetting at the stack limit
  1492  			// since we might have Any type between the limit and the current top.
  1493  			valueTypeStack.resetAtStackLimit()
  1494  			for _, exp := range bl.blockType.Results {
  1495  				valueTypeStack.push(exp)
  1496  			}
  1497  			// We exit if/loop/block, so reset the constraints on the stack manipulation
  1498  			// on values previously pushed by outer blocks.
  1499  			valueTypeStack.popStackLimit()
  1500  		} else if op == OpcodeReturn {
  1501  			// Same formatting as OpcodeEnd on the outer-most block
  1502  			if err := valueTypeStack.requireStackValues(false, "", functionType.Results, false); err != nil {
  1503  				return err
  1504  			}
  1505  			// return instruction is stack-polymorphic.
  1506  			valueTypeStack.unreachable()
  1507  		} else if op == OpcodeDrop {
  1508  			_, err := valueTypeStack.pop()
  1509  			if err != nil {
  1510  				return fmt.Errorf("invalid drop: %v", err)
  1511  			}
  1512  		} else if op == OpcodeSelect || op == OpcodeTypedSelect {
  1513  			if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
  1514  				return fmt.Errorf("type mismatch on 3rd select operand: %v", err)
  1515  			}
  1516  			v1, err := valueTypeStack.pop()
  1517  			if err != nil {
  1518  				return fmt.Errorf("invalid select: %v", err)
  1519  			}
  1520  			v2, err := valueTypeStack.pop()
  1521  			if err != nil {
  1522  				return fmt.Errorf("invalid select: %v", err)
  1523  			}
  1524  
  1525  			if op == OpcodeTypedSelect {
  1526  				if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
  1527  					return fmt.Errorf("%s is invalid as %w", InstructionName(op), err)
  1528  				}
  1529  				pc++
  1530  				if numTypeImmeidates := body[pc]; numTypeImmeidates != 1 {
  1531  					return fmt.Errorf("too many type immediates for %s", InstructionName(op))
  1532  				}
  1533  				pc++
  1534  				tp := body[pc]
  1535  				if tp != ValueTypeI32 && tp != ValueTypeI64 && tp != ValueTypeF32 && tp != ValueTypeF64 &&
  1536  					tp != api.ValueTypeExternref && tp != ValueTypeFuncref && tp != ValueTypeV128 {
  1537  					return fmt.Errorf("invalid type %s for %s", ValueTypeName(tp), OpcodeTypedSelectName)
  1538  				}
  1539  			} else if isReferenceValueType(v1) || isReferenceValueType(v2) {
  1540  				return fmt.Errorf("reference types cannot be used for non typed select instruction")
  1541  			}
  1542  
  1543  			if v1 != v2 && v1 != valueTypeUnknown && v2 != valueTypeUnknown {
  1544  				return fmt.Errorf("type mismatch on 1st and 2nd select operands")
  1545  			}
  1546  			if v1 == valueTypeUnknown {
  1547  				valueTypeStack.push(v2)
  1548  			} else {
  1549  				valueTypeStack.push(v1)
  1550  			}
  1551  		} else if op == OpcodeUnreachable {
  1552  			// unreachable instruction is stack-polymorphic.
  1553  			valueTypeStack.unreachable()
  1554  		} else if op == OpcodeNop {
  1555  		} else {
  1556  			return fmt.Errorf("invalid instruction 0x%x", op)
  1557  		}
  1558  	}
  1559  
  1560  	if len(controlBlockStack.stack) > 0 {
  1561  		return fmt.Errorf("ill-nested block exists")
  1562  	}
  1563  	if valueTypeStack.maximumStackPointer > maxStackValues {
  1564  		return fmt.Errorf("function may have %d stack values, which exceeds limit %d", valueTypeStack.maximumStackPointer, maxStackValues)
  1565  	}
  1566  	return nil
  1567  }
  1568  
  1569  var vecExtractLanes = [...]struct {
  1570  	laneCeil   byte
  1571  	resultType ValueType
  1572  }{
  1573  	OpcodeVecI8x16ExtractLaneS: {laneCeil: 16, resultType: ValueTypeI32},
  1574  	OpcodeVecI8x16ExtractLaneU: {laneCeil: 16, resultType: ValueTypeI32},
  1575  	OpcodeVecI16x8ExtractLaneS: {laneCeil: 8, resultType: ValueTypeI32},
  1576  	OpcodeVecI16x8ExtractLaneU: {laneCeil: 8, resultType: ValueTypeI32},
  1577  	OpcodeVecI32x4ExtractLane:  {laneCeil: 4, resultType: ValueTypeI32},
  1578  	OpcodeVecI64x2ExtractLane:  {laneCeil: 2, resultType: ValueTypeI64},
  1579  	OpcodeVecF32x4ExtractLane:  {laneCeil: 4, resultType: ValueTypeF32},
  1580  	OpcodeVecF64x2ExtractLane:  {laneCeil: 2, resultType: ValueTypeF64},
  1581  }
  1582  
  1583  var vecReplaceLanes = [...]struct {
  1584  	laneCeil  byte
  1585  	paramType ValueType
  1586  }{
  1587  	OpcodeVecI8x16ReplaceLane: {laneCeil: 16, paramType: ValueTypeI32},
  1588  	OpcodeVecI16x8ReplaceLane: {laneCeil: 8, paramType: ValueTypeI32},
  1589  	OpcodeVecI32x4ReplaceLane: {laneCeil: 4, paramType: ValueTypeI32},
  1590  	OpcodeVecI64x2ReplaceLane: {laneCeil: 2, paramType: ValueTypeI64},
  1591  	OpcodeVecF32x4ReplaceLane: {laneCeil: 4, paramType: ValueTypeF32},
  1592  	OpcodeVecF64x2ReplaceLane: {laneCeil: 2, paramType: ValueTypeF64},
  1593  }
  1594  
  1595  var vecStoreLanes = [...]struct {
  1596  	alignMax uint32
  1597  	laneCeil byte
  1598  }{
  1599  	OpcodeVecV128Store64Lane: {alignMax: 64 / 8, laneCeil: 128 / 64},
  1600  	OpcodeVecV128Store32Lane: {alignMax: 32 / 8, laneCeil: 128 / 32},
  1601  	OpcodeVecV128Store16Lane: {alignMax: 16 / 8, laneCeil: 128 / 16},
  1602  	OpcodeVecV128Store8Lane:  {alignMax: 1, laneCeil: 128 / 8},
  1603  }
  1604  
  1605  var vecLoadLanes = [...]struct {
  1606  	alignMax uint32
  1607  	laneCeil byte
  1608  }{
  1609  	OpcodeVecV128Load64Lane: {alignMax: 64 / 8, laneCeil: 128 / 64},
  1610  	OpcodeVecV128Load32Lane: {alignMax: 32 / 8, laneCeil: 128 / 32},
  1611  	OpcodeVecV128Load16Lane: {alignMax: 16 / 8, laneCeil: 128 / 16},
  1612  	OpcodeVecV128Load8Lane:  {alignMax: 1, laneCeil: 128 / 8},
  1613  }
  1614  
  1615  var vecSplatValueTypes = [...]ValueType{
  1616  	OpcodeVecI8x16Splat: ValueTypeI32,
  1617  	OpcodeVecI16x8Splat: ValueTypeI32,
  1618  	OpcodeVecI32x4Splat: ValueTypeI32,
  1619  	OpcodeVecI64x2Splat: ValueTypeI64,
  1620  	OpcodeVecF32x4Splat: ValueTypeF32,
  1621  	OpcodeVecF64x2Splat: ValueTypeF64,
  1622  }
  1623  
  1624  type stacks struct {
  1625  	vs valueTypeStack
  1626  	cs controlBlockStack
  1627  }
  1628  
  1629  func (sts *stacks) reset(functionType *FunctionType) {
  1630  	// Reset valueStack for reuse.
  1631  	sts.vs.stack = sts.vs.stack[:0]
  1632  	sts.vs.stackLimits = sts.vs.stackLimits[:0]
  1633  	sts.vs.maximumStackPointer = 0
  1634  	sts.cs.stack = sts.cs.stack[:0]
  1635  	sts.cs.stack = append(sts.cs.stack, controlBlock{blockType: functionType})
  1636  }
  1637  
  1638  type controlBlockStack struct {
  1639  	stack []controlBlock
  1640  }
  1641  
  1642  func (s *controlBlockStack) pop() *controlBlock {
  1643  	tail := len(s.stack) - 1
  1644  	ret := &s.stack[tail]
  1645  	s.stack = s.stack[:tail]
  1646  	return ret
  1647  }
  1648  
  1649  func (s *controlBlockStack) push(startAt, elseAt, endAt uint64, blockType *FunctionType, blockTypeBytes uint64, op Opcode) {
  1650  	s.stack = append(s.stack, controlBlock{
  1651  		startAt:        startAt,
  1652  		elseAt:         elseAt,
  1653  		endAt:          endAt,
  1654  		blockType:      blockType,
  1655  		blockTypeBytes: blockTypeBytes,
  1656  		op:             op,
  1657  	})
  1658  }
  1659  
  1660  type valueTypeStack struct {
  1661  	stack               []ValueType
  1662  	stackLimits         []int
  1663  	maximumStackPointer int
  1664  	// requireStackValuesTmp is used in requireStackValues function to reduce the allocation.
  1665  	requireStackValuesTmp []ValueType
  1666  }
  1667  
  1668  // Only used in the analyzeFunction below.
  1669  const valueTypeUnknown = ValueType(0xFF)
  1670  
  1671  func (s *valueTypeStack) tryPop() (vt ValueType, limit int, ok bool) {
  1672  	if len(s.stackLimits) > 0 {
  1673  		limit = s.stackLimits[len(s.stackLimits)-1]
  1674  	}
  1675  	stackLen := len(s.stack)
  1676  	if stackLen <= limit {
  1677  		return
  1678  	} else if stackLen == limit+1 && s.stack[limit] == valueTypeUnknown {
  1679  		vt = valueTypeUnknown
  1680  		ok = true
  1681  		return
  1682  	} else {
  1683  		vt = s.stack[stackLen-1]
  1684  		s.stack = s.stack[:stackLen-1]
  1685  		ok = true
  1686  		return
  1687  	}
  1688  }
  1689  
  1690  func (s *valueTypeStack) pop() (ValueType, error) {
  1691  	if vt, limit, ok := s.tryPop(); ok {
  1692  		return vt, nil
  1693  	} else {
  1694  		return 0, fmt.Errorf("invalid operation: trying to pop at %d with limit %d", len(s.stack), limit)
  1695  	}
  1696  }
  1697  
  1698  // popAndVerifyType returns an error if the stack value is unexpected.
  1699  func (s *valueTypeStack) popAndVerifyType(expected ValueType) error {
  1700  	have, _, ok := s.tryPop()
  1701  	if !ok {
  1702  		return fmt.Errorf("%s missing", ValueTypeName(expected))
  1703  	}
  1704  	if have != expected && have != valueTypeUnknown && expected != valueTypeUnknown {
  1705  		return fmt.Errorf("type mismatch: expected %s, but was %s", ValueTypeName(expected), ValueTypeName(have))
  1706  	}
  1707  	return nil
  1708  }
  1709  
  1710  func (s *valueTypeStack) push(v ValueType) {
  1711  	s.stack = append(s.stack, v)
  1712  	if sp := len(s.stack); sp > s.maximumStackPointer {
  1713  		s.maximumStackPointer = sp
  1714  	}
  1715  }
  1716  
  1717  func (s *valueTypeStack) unreachable() {
  1718  	s.resetAtStackLimit()
  1719  	s.stack = append(s.stack, valueTypeUnknown)
  1720  }
  1721  
  1722  func (s *valueTypeStack) resetAtStackLimit() {
  1723  	if len(s.stackLimits) != 0 {
  1724  		s.stack = s.stack[:s.stackLimits[len(s.stackLimits)-1]]
  1725  	} else {
  1726  		s.stack = s.stack[:0]
  1727  	}
  1728  }
  1729  
  1730  func (s *valueTypeStack) popStackLimit() {
  1731  	if len(s.stackLimits) != 0 {
  1732  		s.stackLimits = s.stackLimits[:len(s.stackLimits)-1]
  1733  	}
  1734  }
  1735  
  1736  // pushStackLimit pushes the control frame's bottom of the stack.
  1737  func (s *valueTypeStack) pushStackLimit(params int) {
  1738  	limit := len(s.stack) - params
  1739  	s.stackLimits = append(s.stackLimits, limit)
  1740  }
  1741  
  1742  func (s *valueTypeStack) popParams(oc Opcode, want []ValueType, checkAboveLimit bool) error {
  1743  	return s.requireStackValues(true, InstructionName(oc), want, checkAboveLimit)
  1744  }
  1745  
  1746  func (s *valueTypeStack) popResults(oc Opcode, want []ValueType, checkAboveLimit bool) error {
  1747  	return s.requireStackValues(false, InstructionName(oc), want, checkAboveLimit)
  1748  }
  1749  
  1750  func (s *valueTypeStack) requireStackValues(
  1751  	isParam bool,
  1752  	context string,
  1753  	want []ValueType,
  1754  	checkAboveLimit bool,
  1755  ) error {
  1756  	limit := 0
  1757  	if len(s.stackLimits) > 0 {
  1758  		limit = s.stackLimits[len(s.stackLimits)-1]
  1759  	}
  1760  	// Iterate backwards as we are comparing the desired slice against stack value types.
  1761  	countWanted := len(want)
  1762  
  1763  	// First, check if there are enough values on the stack.
  1764  	s.requireStackValuesTmp = s.requireStackValuesTmp[:0]
  1765  	for i := countWanted - 1; i >= 0; i-- {
  1766  		popped, _, ok := s.tryPop()
  1767  		if !ok {
  1768  			if len(s.requireStackValuesTmp) > len(want) {
  1769  				return typeCountError(isParam, context, s.requireStackValuesTmp, want)
  1770  			}
  1771  			return typeCountError(isParam, context, s.requireStackValuesTmp, want)
  1772  		}
  1773  		s.requireStackValuesTmp = append(s.requireStackValuesTmp, popped)
  1774  	}
  1775  
  1776  	// Now, check if there are too many values.
  1777  	if checkAboveLimit {
  1778  		if !(limit == len(s.stack) || (limit+1 == len(s.stack) && s.stack[limit] == valueTypeUnknown)) {
  1779  			return typeCountError(isParam, context, append(s.stack, want...), want)
  1780  		}
  1781  	}
  1782  
  1783  	// Finally, check the types of the values:
  1784  	for i, v := range s.requireStackValuesTmp {
  1785  		nextWant := want[countWanted-i-1] // have is in reverse order (stack)
  1786  		if v != nextWant && v != valueTypeUnknown && nextWant != valueTypeUnknown {
  1787  			return typeMismatchError(isParam, context, v, nextWant, i)
  1788  		}
  1789  	}
  1790  	return nil
  1791  }
  1792  
  1793  // typeMismatchError returns an error similar to go compiler's error on type mismatch.
  1794  func typeMismatchError(isParam bool, context string, have ValueType, want ValueType, i int) error {
  1795  	var ret strings.Builder
  1796  	ret.WriteString("cannot use ")
  1797  	ret.WriteString(ValueTypeName(have))
  1798  	if context != "" {
  1799  		ret.WriteString(" in ")
  1800  		ret.WriteString(context)
  1801  		ret.WriteString(" block")
  1802  	}
  1803  	if isParam {
  1804  		ret.WriteString(" as param")
  1805  	} else {
  1806  		ret.WriteString(" as result")
  1807  	}
  1808  	ret.WriteString("[")
  1809  	ret.WriteString(strconv.Itoa(i))
  1810  	ret.WriteString("] type ")
  1811  	ret.WriteString(ValueTypeName(want))
  1812  	return errors.New(ret.String())
  1813  }
  1814  
  1815  // typeCountError returns an error similar to go compiler's error on type count mismatch.
  1816  func typeCountError(isParam bool, context string, have []ValueType, want []ValueType) error {
  1817  	var ret strings.Builder
  1818  	if len(have) > len(want) {
  1819  		ret.WriteString("too many ")
  1820  	} else {
  1821  		ret.WriteString("not enough ")
  1822  	}
  1823  	if isParam {
  1824  		ret.WriteString("params")
  1825  	} else {
  1826  		ret.WriteString("results")
  1827  	}
  1828  	if context != "" {
  1829  		if isParam {
  1830  			ret.WriteString(" for ")
  1831  		} else {
  1832  			ret.WriteString(" in ")
  1833  		}
  1834  		ret.WriteString(context)
  1835  		ret.WriteString(" block")
  1836  	}
  1837  	ret.WriteString("\n\thave (")
  1838  	writeValueTypes(have, &ret)
  1839  	ret.WriteString(")\n\twant (")
  1840  	writeValueTypes(want, &ret)
  1841  	ret.WriteByte(')')
  1842  	return errors.New(ret.String())
  1843  }
  1844  
  1845  func writeValueTypes(vts []ValueType, ret *strings.Builder) {
  1846  	switch len(vts) {
  1847  	case 0:
  1848  	case 1:
  1849  		ret.WriteString(ValueTypeName(vts[0]))
  1850  	default:
  1851  		ret.WriteString(ValueTypeName(vts[0]))
  1852  		for _, vt := range vts[1:] {
  1853  			ret.WriteString(", ")
  1854  			ret.WriteString(ValueTypeName(vt))
  1855  		}
  1856  	}
  1857  }
  1858  
  1859  func (s *valueTypeStack) String() string {
  1860  	var typeStrs, limits []string
  1861  	for _, v := range s.stack {
  1862  		var str string
  1863  		if v == valueTypeUnknown {
  1864  			str = "unknown"
  1865  		} else {
  1866  			str = ValueTypeName(v)
  1867  		}
  1868  		typeStrs = append(typeStrs, str)
  1869  	}
  1870  	for _, d := range s.stackLimits {
  1871  		limits = append(limits, fmt.Sprintf("%d", d))
  1872  	}
  1873  	return fmt.Sprintf("{stack: [%s], limits: [%s]}",
  1874  		strings.Join(typeStrs, ", "), strings.Join(limits, ","))
  1875  }
  1876  
  1877  type controlBlock struct {
  1878  	startAt, elseAt, endAt uint64
  1879  	blockType              *FunctionType
  1880  	blockTypeBytes         uint64
  1881  	// op is zero when the outermost block
  1882  	op Opcode
  1883  }
  1884  
  1885  // DecodeBlockType decodes the type index from a positive 33-bit signed integer. Negative numbers indicate up to one
  1886  // WebAssembly 1.0 (20191205) compatible result type. Positive numbers are decoded when `enabledFeatures` include
  1887  // CoreFeatureMultiValue and include an index in the Module.TypeSection.
  1888  //
  1889  // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-blocktype
  1890  // See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/multi-value/Overview.md
  1891  func DecodeBlockType(types []FunctionType, r *bytes.Reader, enabledFeatures api.CoreFeatures) (*FunctionType, uint64, error) {
  1892  	raw, num, err := leb128.DecodeInt33AsInt64(r)
  1893  	if err != nil {
  1894  		return nil, 0, fmt.Errorf("decode int33: %w", err)
  1895  	}
  1896  
  1897  	var ret *FunctionType
  1898  	switch raw {
  1899  	case -64: // 0x40 in original byte = nil
  1900  		ret = blockType_v_v
  1901  	case -1: // 0x7f in original byte = i32
  1902  		ret = blockType_v_i32
  1903  	case -2: // 0x7e in original byte = i64
  1904  		ret = blockType_v_i64
  1905  	case -3: // 0x7d in original byte = f32
  1906  		ret = blockType_v_f32
  1907  	case -4: // 0x7c in original byte = f64
  1908  		ret = blockType_v_f64
  1909  	case -5: // 0x7b in original byte = v128
  1910  		ret = blockType_v_v128
  1911  	case -16: // 0x70 in original byte = funcref
  1912  		ret = blockType_v_funcref
  1913  	case -17: // 0x6f in original byte = externref
  1914  		ret = blockType_v_externref
  1915  	default:
  1916  		if err = enabledFeatures.RequireEnabled(api.CoreFeatureMultiValue); err != nil {
  1917  			return nil, num, fmt.Errorf("block with function type return invalid as %v", err)
  1918  		}
  1919  		if raw < 0 || (raw >= int64(len(types))) {
  1920  			return nil, 0, fmt.Errorf("type index out of range: %d", raw)
  1921  		}
  1922  		ret = &types[raw]
  1923  	}
  1924  	return ret, num, err
  1925  }
  1926  
  1927  // These block types are defined as globals in order to avoid allocations in DecodeBlockType.
  1928  var (
  1929  	blockType_v_v         = &FunctionType{}
  1930  	blockType_v_i32       = &FunctionType{Results: []ValueType{ValueTypeI32}, ResultNumInUint64: 1}
  1931  	blockType_v_i64       = &FunctionType{Results: []ValueType{ValueTypeI64}, ResultNumInUint64: 1}
  1932  	blockType_v_f32       = &FunctionType{Results: []ValueType{ValueTypeF32}, ResultNumInUint64: 1}
  1933  	blockType_v_f64       = &FunctionType{Results: []ValueType{ValueTypeF64}, ResultNumInUint64: 1}
  1934  	blockType_v_v128      = &FunctionType{Results: []ValueType{ValueTypeV128}, ResultNumInUint64: 2}
  1935  	blockType_v_funcref   = &FunctionType{Results: []ValueType{ValueTypeFuncref}, ResultNumInUint64: 1}
  1936  	blockType_v_externref = &FunctionType{Results: []ValueType{ValueTypeExternref}, ResultNumInUint64: 1}
  1937  )
  1938  
  1939  // SplitCallStack returns the input stack resliced to the count of params and
  1940  // results, or errors if it isn't long enough for either.
  1941  func SplitCallStack(ft *FunctionType, stack []uint64) (params []uint64, results []uint64, err error) {
  1942  	stackLen := len(stack)
  1943  	if n := ft.ParamNumInUint64; n > stackLen {
  1944  		return nil, nil, fmt.Errorf("need %d params, but stack size is %d", n, stackLen)
  1945  	} else if n > 0 {
  1946  		params = stack[:n]
  1947  	}
  1948  	if n := ft.ResultNumInUint64; n > stackLen {
  1949  		return nil, nil, fmt.Errorf("need %d results, but stack size is %d", n, stackLen)
  1950  	} else if n > 0 {
  1951  		results = stack[:n]
  1952  	}
  1953  	return
  1954  }
  1955  

View as plain text