github.com/tetratelabs/wazero@v1.7.3-0.20240513003603-48f702e154b5/internal/wasm/func_validation.go (about)

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