github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/engine/wazevo/testcases/testcases.go (about)

     1  package testcases
     2  
     3  import (
     4  	"math"
     5  
     6  	"github.com/wasilibs/wazerox/internal/leb128"
     7  	"github.com/wasilibs/wazerox/internal/wasm"
     8  )
     9  
    10  const ExportedFunctionName = "f"
    11  
    12  var (
    13  	Empty     = TestCase{Name: "empty", Module: SingleFunctionModule(vv, []byte{wasm.OpcodeEnd}, nil)}
    14  	Constants = TestCase{Name: "consts", Module: SingleFunctionModule(wasm.FunctionType{
    15  		Results: []wasm.ValueType{i32, i64, f32, f64},
    16  	}, []byte{
    17  		wasm.OpcodeI32Const, 1,
    18  		wasm.OpcodeI64Const, 2,
    19  		wasm.OpcodeF32Const,
    20  		byte(math.Float32bits(32.0)),
    21  		byte(math.Float32bits(32.0) >> 8),
    22  		byte(math.Float32bits(32.0) >> 16),
    23  		byte(math.Float32bits(32.0) >> 24),
    24  		wasm.OpcodeF64Const,
    25  		byte(math.Float64bits(64.0)),
    26  		byte(math.Float64bits(64.0) >> 8),
    27  		byte(math.Float64bits(64.0) >> 16),
    28  		byte(math.Float64bits(64.0) >> 24),
    29  		byte(math.Float64bits(64.0) >> 32),
    30  		byte(math.Float64bits(64.0) >> 40),
    31  		byte(math.Float64bits(64.0) >> 48),
    32  		byte(math.Float64bits(64.0) >> 56),
    33  		wasm.OpcodeEnd,
    34  	}, nil)}
    35  	Unreachable        = TestCase{Name: "unreachable", Module: SingleFunctionModule(vv, []byte{wasm.OpcodeUnreachable, wasm.OpcodeEnd}, nil)}
    36  	OnlyReturn         = TestCase{Name: "only_return", Module: SingleFunctionModule(vv, []byte{wasm.OpcodeReturn, wasm.OpcodeEnd}, nil)}
    37  	Params             = TestCase{Name: "params", Module: SingleFunctionModule(i32f32f64_v, []byte{wasm.OpcodeReturn, wasm.OpcodeEnd}, nil)}
    38  	AddSubParamsReturn = TestCase{
    39  		Name: "add_sub_params_return",
    40  		Module: SingleFunctionModule(i32i32_i32, []byte{
    41  			wasm.OpcodeLocalGet, 0,
    42  			wasm.OpcodeLocalGet, 1,
    43  			wasm.OpcodeI32Add,
    44  			wasm.OpcodeLocalGet, 0,
    45  			wasm.OpcodeI32Sub,
    46  			wasm.OpcodeEnd,
    47  		}, nil),
    48  	}
    49  	Locals       = TestCase{Name: "locals", Module: SingleFunctionModule(vv, []byte{wasm.OpcodeEnd}, []wasm.ValueType{i32, i64, f32, f64})}
    50  	LocalsParams = TestCase{
    51  		Name: "locals_params",
    52  		Module: SingleFunctionModule(
    53  			i64f32f64_i64f32f64,
    54  			[]byte{
    55  				wasm.OpcodeLocalGet, 0,
    56  				wasm.OpcodeLocalGet, 0,
    57  				wasm.OpcodeI64Add,
    58  				wasm.OpcodeLocalGet, 0,
    59  				wasm.OpcodeI64Sub,
    60  
    61  				wasm.OpcodeLocalGet, 1,
    62  				wasm.OpcodeLocalGet, 1,
    63  				wasm.OpcodeF32Add,
    64  				wasm.OpcodeLocalGet, 1,
    65  				wasm.OpcodeF32Sub,
    66  				wasm.OpcodeLocalGet, 1,
    67  				wasm.OpcodeF32Mul,
    68  				wasm.OpcodeLocalGet, 1,
    69  				wasm.OpcodeF32Div,
    70  				wasm.OpcodeLocalGet, 1,
    71  				wasm.OpcodeF32Max,
    72  				wasm.OpcodeLocalGet, 1,
    73  				wasm.OpcodeF32Min,
    74  
    75  				wasm.OpcodeLocalGet, 2,
    76  				wasm.OpcodeLocalGet, 2,
    77  				wasm.OpcodeF64Add,
    78  				wasm.OpcodeLocalGet, 2,
    79  				wasm.OpcodeF64Sub,
    80  				wasm.OpcodeLocalGet, 2,
    81  				wasm.OpcodeF64Mul,
    82  				wasm.OpcodeLocalGet, 2,
    83  				wasm.OpcodeF64Div,
    84  				wasm.OpcodeLocalGet, 2,
    85  				wasm.OpcodeF64Max,
    86  				wasm.OpcodeLocalGet, 2,
    87  				wasm.OpcodeF64Min,
    88  
    89  				wasm.OpcodeEnd,
    90  			}, []wasm.ValueType{i32, i64, f32, f64},
    91  		),
    92  	}
    93  	LocalParamReturn = TestCase{
    94  		Name: "local_param_return",
    95  		Module: SingleFunctionModule(i32_i32i32, []byte{
    96  			wasm.OpcodeLocalGet, 0,
    97  			wasm.OpcodeLocalGet, 1,
    98  			wasm.OpcodeEnd,
    99  		}, []wasm.ValueType{i32}),
   100  	}
   101  	LocalParamTeeReturn = TestCase{
   102  		Name: "local_param_tee_return",
   103  		Module: SingleFunctionModule(i32_i32i32, []byte{
   104  			wasm.OpcodeLocalGet, 0,
   105  			wasm.OpcodeLocalTee, 1,
   106  			wasm.OpcodeLocalGet, 1,
   107  			wasm.OpcodeEnd,
   108  		}, []wasm.ValueType{i32}),
   109  	}
   110  	SwapParamAndReturn = TestCase{
   111  		Name: "swap_param_and_return",
   112  		Module: SingleFunctionModule(i32i32_i32i32, []byte{
   113  			wasm.OpcodeLocalGet, 1,
   114  			wasm.OpcodeLocalGet, 0,
   115  			wasm.OpcodeEnd,
   116  		}, nil),
   117  	}
   118  	Selects = TestCase{
   119  		Name: "swap_param_and_return",
   120  		Module: SingleFunctionModule(i32i32i64i64f32f32f64f64_i32i64, []byte{
   121  			// i32 select.
   122  			wasm.OpcodeLocalGet, 0, // x
   123  			wasm.OpcodeLocalGet, 1, // y
   124  			// cond
   125  			wasm.OpcodeLocalGet, 2,
   126  			wasm.OpcodeLocalGet, 3,
   127  			wasm.OpcodeI64Eq,
   128  			wasm.OpcodeSelect,
   129  
   130  			// i64 select.
   131  			wasm.OpcodeLocalGet, 2, // x
   132  			wasm.OpcodeLocalGet, 3, // y
   133  			wasm.OpcodeLocalGet, 1, // cond
   134  			wasm.OpcodeTypedSelect, 1, wasm.ValueTypeI64,
   135  
   136  			// f32 select.
   137  			wasm.OpcodeLocalGet, 4, // x
   138  			wasm.OpcodeLocalGet, 5, // y
   139  			// cond
   140  			wasm.OpcodeLocalGet, 6,
   141  			wasm.OpcodeLocalGet, 7,
   142  			wasm.OpcodeF64Gt,
   143  			wasm.OpcodeTypedSelect, 1, wasm.ValueTypeF32,
   144  
   145  			// f64 select.
   146  			wasm.OpcodeLocalGet, 6, // x
   147  			wasm.OpcodeLocalGet, 7, // y
   148  			// cond
   149  			wasm.OpcodeLocalGet, 4,
   150  			wasm.OpcodeLocalGet, 5,
   151  			wasm.OpcodeF32Ne,
   152  			wasm.OpcodeTypedSelect, 1, wasm.ValueTypeF64,
   153  
   154  			wasm.OpcodeEnd,
   155  		}, nil),
   156  	}
   157  	SwapParamsAndReturn = TestCase{
   158  		Name: "swap_params_and_return",
   159  		Module: SingleFunctionModule(i32i32_i32i32, []byte{
   160  			wasm.OpcodeLocalGet, 1,
   161  			wasm.OpcodeLocalGet, 0,
   162  			wasm.OpcodeLocalSet, 1,
   163  			wasm.OpcodeLocalSet, 0,
   164  			wasm.OpcodeBlock, blockSignature_vv,
   165  			wasm.OpcodeEnd,
   166  			wasm.OpcodeLocalGet, 0,
   167  			wasm.OpcodeLocalGet, 1,
   168  			wasm.OpcodeEnd,
   169  		}, nil),
   170  	}
   171  	BlockBr = TestCase{
   172  		Name: "block_br",
   173  		Module: SingleFunctionModule(vv, []byte{
   174  			wasm.OpcodeBlock, 0,
   175  			wasm.OpcodeBr, 0,
   176  			wasm.OpcodeEnd,
   177  			wasm.OpcodeEnd,
   178  		}, []wasm.ValueType{i32, i64, f32, f64}),
   179  	}
   180  	BlockBrIf = TestCase{
   181  		Name: "block_br_if",
   182  		Module: SingleFunctionModule(vv, []byte{
   183  			wasm.OpcodeBlock, 0,
   184  			wasm.OpcodeLocalGet, 0,
   185  			wasm.OpcodeBrIf, 0,
   186  			wasm.OpcodeUnreachable,
   187  			wasm.OpcodeEnd,
   188  			wasm.OpcodeEnd,
   189  		}, []wasm.ValueType{i32}),
   190  	}
   191  	LoopBr = TestCase{
   192  		Name: "loop_br",
   193  		Module: SingleFunctionModule(vv, []byte{
   194  			wasm.OpcodeLoop, 0,
   195  			wasm.OpcodeBr, 0,
   196  			wasm.OpcodeEnd,
   197  			wasm.OpcodeEnd,
   198  		}, []wasm.ValueType{}),
   199  	}
   200  	LoopBrWithParamResults = TestCase{
   201  		Name: "loop_with_param_results",
   202  		Module: SingleFunctionModule(i32i32_i32, []byte{
   203  			wasm.OpcodeLocalGet, 0,
   204  			wasm.OpcodeLocalGet, 1,
   205  			wasm.OpcodeLoop, 0,
   206  			wasm.OpcodeI32Const, 1,
   207  			wasm.OpcodeBrIf, 0,
   208  			wasm.OpcodeDrop,
   209  			wasm.OpcodeEnd,
   210  			wasm.OpcodeEnd,
   211  		}, []wasm.ValueType{}),
   212  	}
   213  	LoopBrIf = TestCase{
   214  		Name: "loop_br_if",
   215  		Module: SingleFunctionModule(vv, []byte{
   216  			wasm.OpcodeLoop, 0,
   217  			wasm.OpcodeI32Const, 1,
   218  			wasm.OpcodeBrIf, 0,
   219  			wasm.OpcodeReturn,
   220  			wasm.OpcodeEnd,
   221  			wasm.OpcodeEnd,
   222  		}, []wasm.ValueType{}),
   223  	}
   224  	BlockBlockBr = TestCase{
   225  		Name: "block_block_br",
   226  		Module: SingleFunctionModule(vv, []byte{
   227  			wasm.OpcodeBlock, 0,
   228  			wasm.OpcodeBlock, 0,
   229  			wasm.OpcodeBr, 1,
   230  			wasm.OpcodeEnd,
   231  			wasm.OpcodeEnd,
   232  			wasm.OpcodeEnd,
   233  		}, []wasm.ValueType{i32, i64, f32, f64}),
   234  	}
   235  	IfWithoutElse = TestCase{
   236  		Name: "if_without_else",
   237  		Module: SingleFunctionModule(vv, []byte{
   238  			wasm.OpcodeLocalGet, 0,
   239  			wasm.OpcodeIf, 0,
   240  			wasm.OpcodeEnd,
   241  			wasm.OpcodeEnd,
   242  		}, []wasm.ValueType{i32}),
   243  	}
   244  	IfElse = TestCase{
   245  		Name: "if_else",
   246  		Module: SingleFunctionModule(vv, []byte{
   247  			wasm.OpcodeLocalGet, 0,
   248  			wasm.OpcodeIf, 0,
   249  			wasm.OpcodeElse,
   250  			wasm.OpcodeBr, 1,
   251  			wasm.OpcodeEnd,
   252  			wasm.OpcodeEnd,
   253  		}, []wasm.ValueType{i32}),
   254  	}
   255  	SinglePredecessorLocalRefs = TestCase{
   256  		Name: "single_predecessor_local_refs",
   257  		Module: &wasm.Module{
   258  			TypeSection:     []wasm.FunctionType{vv, v_i32},
   259  			FunctionSection: []wasm.Index{1},
   260  			CodeSection: []wasm.Code{{
   261  				LocalTypes: []wasm.ValueType{i32, i32, i32},
   262  				Body: []byte{
   263  					wasm.OpcodeLocalGet, 0,
   264  					wasm.OpcodeIf, 0,
   265  					// This is defined in the first block which is the sole predecessor of If.
   266  					wasm.OpcodeLocalGet, 2,
   267  					wasm.OpcodeReturn,
   268  					wasm.OpcodeElse,
   269  					wasm.OpcodeEnd,
   270  					// This is defined in the first block which is the sole predecessor of this block.
   271  					// Note that If block will never reach here because it's returning early.
   272  					wasm.OpcodeLocalGet, 0,
   273  					wasm.OpcodeEnd,
   274  				},
   275  			}},
   276  		},
   277  	}
   278  	MultiPredecessorLocalRef = TestCase{
   279  		Name: "multi_predecessor_local_ref",
   280  		Module: SingleFunctionModule(i32i32_i32, []byte{
   281  			wasm.OpcodeLocalGet, 0,
   282  			wasm.OpcodeIf, blockSignature_vv,
   283  			// Set the first param to the local.
   284  			wasm.OpcodeLocalGet, 0,
   285  			wasm.OpcodeLocalSet, 2,
   286  			wasm.OpcodeElse,
   287  			// Set the second param to the local.
   288  			wasm.OpcodeLocalGet, 1,
   289  			wasm.OpcodeLocalSet, 2,
   290  			wasm.OpcodeEnd,
   291  
   292  			// Return the local as a result which has multiple definitions in predecessors (Then and Else).
   293  			wasm.OpcodeLocalGet, 2,
   294  			wasm.OpcodeEnd,
   295  		}, []wasm.ValueType{i32}),
   296  	}
   297  	ReferenceValueFromUnsealedBlock = TestCase{
   298  		Name: "reference_value_from_unsealed_block",
   299  		Module: SingleFunctionModule(i32_i32, []byte{
   300  			wasm.OpcodeLoop, blockSignature_vv,
   301  			// Loop will not be sealed until we reach the end,
   302  			// so this will result in referencing the unsealed definition search.
   303  			wasm.OpcodeLocalGet, 0,
   304  			wasm.OpcodeReturn,
   305  			wasm.OpcodeEnd,
   306  			wasm.OpcodeLocalGet, 0,
   307  			wasm.OpcodeEnd,
   308  		}, []wasm.ValueType{i32}),
   309  	}
   310  	ReferenceValueFromUnsealedBlock2 = TestCase{
   311  		Name: "reference_value_from_unsealed_block2",
   312  		Module: SingleFunctionModule(i32_i32, []byte{
   313  			wasm.OpcodeLoop, blockSignature_vv,
   314  			wasm.OpcodeBlock, blockSignature_vv,
   315  
   316  			wasm.OpcodeLocalGet, 0,
   317  			wasm.OpcodeBrIf, 1,
   318  			wasm.OpcodeEnd,
   319  
   320  			wasm.OpcodeEnd,
   321  			wasm.OpcodeI32Const, 0,
   322  			wasm.OpcodeEnd,
   323  		}, []wasm.ValueType{}),
   324  	}
   325  	ReferenceValueFromUnsealedBlock3 = TestCase{
   326  		Name: "reference_value_from_unsealed_block3",
   327  		Module: SingleFunctionModule(i32_v, []byte{
   328  			wasm.OpcodeLoop, blockSignature_vv,
   329  			wasm.OpcodeBlock, blockSignature_vv,
   330  			wasm.OpcodeLocalGet, 0,
   331  			wasm.OpcodeBrIf, 2,
   332  			wasm.OpcodeEnd,
   333  			wasm.OpcodeI32Const, 1,
   334  			wasm.OpcodeLocalSet, 0,
   335  			wasm.OpcodeBr, 0,
   336  			wasm.OpcodeEnd,
   337  			wasm.OpcodeEnd,
   338  		}, []wasm.ValueType{}),
   339  	}
   340  	Call = TestCase{
   341  		Name: "call",
   342  		Module: &wasm.Module{
   343  			TypeSection:     []wasm.FunctionType{v_i32i32, v_i32, i32i32_i32, i32_i32i32},
   344  			FunctionSection: []wasm.Index{0, 1, 2, 3},
   345  			CodeSection: []wasm.Code{
   346  				{Body: []byte{
   347  					// Call v_i32.
   348  					wasm.OpcodeCall, 1,
   349  					// Call i32i32_i32.
   350  					wasm.OpcodeI32Const, 5,
   351  					wasm.OpcodeCall, 2,
   352  					// Call i32_i32i32.
   353  					wasm.OpcodeCall, 3,
   354  					wasm.OpcodeEnd,
   355  				}},
   356  				// v_i32: return 100.
   357  				{Body: []byte{wasm.OpcodeI32Const, 40, wasm.OpcodeEnd}},
   358  				// i32i32_i32: adds.
   359  				{Body: []byte{wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeI32Add, wasm.OpcodeEnd}},
   360  				// i32_i32i32: duplicates.
   361  				{Body: []byte{wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 0, wasm.OpcodeEnd}},
   362  			},
   363  			ExportSection: []wasm.Export{{Name: ExportedFunctionName, Index: 0, Type: wasm.ExternTypeFunc}},
   364  		},
   365  	}
   366  	ManyMiddleValues = TestCase{
   367  		Name: "many_middle_values",
   368  		Module: SingleFunctionModule(wasm.FunctionType{
   369  			Params:  []wasm.ValueType{i32, f32},
   370  			Results: []wasm.ValueType{i32, f32},
   371  		}, []byte{
   372  			wasm.OpcodeLocalGet, 0, wasm.OpcodeI32Const, 1, wasm.OpcodeI32Mul,
   373  			wasm.OpcodeLocalGet, 0, wasm.OpcodeI32Const, 2, wasm.OpcodeI32Mul,
   374  			wasm.OpcodeLocalGet, 0, wasm.OpcodeI32Const, 3, wasm.OpcodeI32Mul,
   375  			wasm.OpcodeLocalGet, 0, wasm.OpcodeI32Const, 4, wasm.OpcodeI32Mul,
   376  			wasm.OpcodeLocalGet, 0, wasm.OpcodeI32Const, 5, wasm.OpcodeI32Mul,
   377  			wasm.OpcodeLocalGet, 0, wasm.OpcodeI32Const, 6, wasm.OpcodeI32Mul,
   378  			wasm.OpcodeLocalGet, 0, wasm.OpcodeI32Const, 7, wasm.OpcodeI32Mul,
   379  			wasm.OpcodeLocalGet, 0, wasm.OpcodeI32Const, 8, wasm.OpcodeI32Mul,
   380  			wasm.OpcodeLocalGet, 0, wasm.OpcodeI32Const, 9, wasm.OpcodeI32Mul,
   381  			wasm.OpcodeLocalGet, 0, wasm.OpcodeI32Const, 10, wasm.OpcodeI32Mul,
   382  			wasm.OpcodeLocalGet, 0, wasm.OpcodeI32Const, 11, wasm.OpcodeI32Mul,
   383  			wasm.OpcodeLocalGet, 0, wasm.OpcodeI32Const, 12, wasm.OpcodeI32Mul,
   384  			wasm.OpcodeLocalGet, 0, wasm.OpcodeI32Const, 13, wasm.OpcodeI32Mul,
   385  			wasm.OpcodeLocalGet, 0, wasm.OpcodeI32Const, 14, wasm.OpcodeI32Mul,
   386  			wasm.OpcodeLocalGet, 0, wasm.OpcodeI32Const, 15, wasm.OpcodeI32Mul,
   387  			wasm.OpcodeLocalGet, 0, wasm.OpcodeI32Const, 16, wasm.OpcodeI32Mul,
   388  			wasm.OpcodeLocalGet, 0, wasm.OpcodeI32Const, 17, wasm.OpcodeI32Mul,
   389  			wasm.OpcodeLocalGet, 0, wasm.OpcodeI32Const, 18, wasm.OpcodeI32Mul,
   390  			wasm.OpcodeLocalGet, 0, wasm.OpcodeI32Const, 19, wasm.OpcodeI32Mul,
   391  			wasm.OpcodeLocalGet, 0, wasm.OpcodeI32Const, 20, wasm.OpcodeI32Mul,
   392  
   393  			wasm.OpcodeI32Add, wasm.OpcodeI32Add, wasm.OpcodeI32Add, wasm.OpcodeI32Add, wasm.OpcodeI32Add,
   394  			wasm.OpcodeI32Add, wasm.OpcodeI32Add, wasm.OpcodeI32Add, wasm.OpcodeI32Add, wasm.OpcodeI32Add,
   395  			wasm.OpcodeI32Add, wasm.OpcodeI32Add, wasm.OpcodeI32Add, wasm.OpcodeI32Add, wasm.OpcodeI32Add,
   396  			wasm.OpcodeI32Add, wasm.OpcodeI32Add, wasm.OpcodeI32Add, wasm.OpcodeI32Add,
   397  
   398  			wasm.OpcodeLocalGet, 1, wasm.OpcodeF32Const, 0, 0, 0x80, 0x3f, wasm.OpcodeF32Mul,
   399  			wasm.OpcodeLocalGet, 1, wasm.OpcodeF32Const, 0, 0, 0, 0x40, wasm.OpcodeF32Mul,
   400  			wasm.OpcodeLocalGet, 1, wasm.OpcodeF32Const, 0, 0, 0x40, 0x40, wasm.OpcodeF32Mul,
   401  			wasm.OpcodeLocalGet, 1, wasm.OpcodeF32Const, 0, 0, 0x80, 0x40, wasm.OpcodeF32Mul,
   402  			wasm.OpcodeLocalGet, 1, wasm.OpcodeF32Const, 0, 0, 0xa0, 0x40, wasm.OpcodeF32Mul,
   403  			wasm.OpcodeLocalGet, 1, wasm.OpcodeF32Const, 0, 0, 0xc0, 0x40, wasm.OpcodeF32Mul,
   404  			wasm.OpcodeLocalGet, 1, wasm.OpcodeF32Const, 0, 0, 0xe0, 0x40, wasm.OpcodeF32Mul,
   405  			wasm.OpcodeLocalGet, 1, wasm.OpcodeF32Const, 0, 0, 0, 0x41, wasm.OpcodeF32Mul,
   406  			wasm.OpcodeLocalGet, 1, wasm.OpcodeF32Const, 0, 0, 0x10, 0x41, wasm.OpcodeF32Mul,
   407  			wasm.OpcodeLocalGet, 1, wasm.OpcodeF32Const, 0, 0, 0x20, 0x41, wasm.OpcodeF32Mul,
   408  			wasm.OpcodeLocalGet, 1, wasm.OpcodeF32Const, 0, 0, 0x30, 0x41, wasm.OpcodeF32Mul,
   409  			wasm.OpcodeLocalGet, 1, wasm.OpcodeF32Const, 0, 0, 0x40, 0x41, wasm.OpcodeF32Mul,
   410  			wasm.OpcodeLocalGet, 1, wasm.OpcodeF32Const, 0, 0, 0x50, 0x41, wasm.OpcodeF32Mul,
   411  			wasm.OpcodeLocalGet, 1, wasm.OpcodeF32Const, 0, 0, 0x60, 0x41, wasm.OpcodeF32Mul,
   412  			wasm.OpcodeLocalGet, 1, wasm.OpcodeF32Const, 0, 0, 0x70, 0x41, wasm.OpcodeF32Mul,
   413  			wasm.OpcodeLocalGet, 1, wasm.OpcodeF32Const, 0, 0, 0x80, 0x41, wasm.OpcodeF32Mul,
   414  			wasm.OpcodeLocalGet, 1, wasm.OpcodeF32Const, 0, 0, 0x88, 0x41, wasm.OpcodeF32Mul,
   415  			wasm.OpcodeLocalGet, 1, wasm.OpcodeF32Const, 0, 0, 0x90, 0x41, wasm.OpcodeF32Mul,
   416  			wasm.OpcodeLocalGet, 1, wasm.OpcodeF32Const, 0, 0, 0x98, 0x41, wasm.OpcodeF32Mul,
   417  			wasm.OpcodeLocalGet, 1, wasm.OpcodeF32Const, 0, 0, 0xa0, 0x41, wasm.OpcodeF32Mul,
   418  
   419  			wasm.OpcodeF32Add, wasm.OpcodeF32Add, wasm.OpcodeF32Add, wasm.OpcodeF32Add, wasm.OpcodeF32Add,
   420  			wasm.OpcodeF32Add, wasm.OpcodeF32Add, wasm.OpcodeF32Add, wasm.OpcodeF32Add, wasm.OpcodeF32Add,
   421  			wasm.OpcodeF32Add, wasm.OpcodeF32Add, wasm.OpcodeF32Add, wasm.OpcodeF32Add, wasm.OpcodeF32Add,
   422  			wasm.OpcodeF32Add, wasm.OpcodeF32Add, wasm.OpcodeF32Add, wasm.OpcodeF32Add,
   423  
   424  			wasm.OpcodeEnd,
   425  		}, nil),
   426  	}
   427  	CallManyParams = TestCase{
   428  		Name: "call_many_params",
   429  		Module: &wasm.Module{
   430  			TypeSection: []wasm.FunctionType{
   431  				{Params: []wasm.ValueType{i32, i64, f32, f64}},
   432  				{
   433  					Params: []wasm.ValueType{
   434  						i32, i64, f32, f64, i32, i64, f32, f64,
   435  						i32, i64, f32, f64, i32, i64, f32, f64,
   436  						i32, i64, f32, f64, i32, i64, f32, f64,
   437  						i32, i64, f32, f64, i32, i64, f32, f64,
   438  						i32, i64, f32, f64, i32, i64, f32, f64,
   439  					},
   440  				},
   441  			},
   442  			FunctionSection: []wasm.Index{0, 1},
   443  			CodeSection: []wasm.Code{
   444  				{
   445  					Body: []byte{
   446  						wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   447  						wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   448  						wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   449  						wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   450  						wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   451  						wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   452  						wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   453  						wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   454  						wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   455  						wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   456  						wasm.OpcodeCall, 1,
   457  						wasm.OpcodeEnd,
   458  					},
   459  				},
   460  				{Body: []byte{wasm.OpcodeEnd}},
   461  			},
   462  		},
   463  	}
   464  	CallManyReturns = TestCase{
   465  		Name: "call_many_returns",
   466  		Module: &wasm.Module{
   467  			TypeSection: []wasm.FunctionType{
   468  				{
   469  					Params: []wasm.ValueType{i32, i64, f32, f64},
   470  					Results: []wasm.ValueType{
   471  						i32, i64, f32, f64, i32, i64, f32, f64,
   472  						i32, i64, f32, f64, i32, i64, f32, f64,
   473  						i32, i64, f32, f64, i32, i64, f32, f64,
   474  						i32, i64, f32, f64, i32, i64, f32, f64,
   475  						i32, i64, f32, f64, i32, i64, f32, f64,
   476  					},
   477  				},
   478  			},
   479  			FunctionSection: []wasm.Index{0, 0},
   480  			CodeSection: []wasm.Code{
   481  				{
   482  					Body: []byte{
   483  						wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   484  						wasm.OpcodeCall, 1,
   485  						wasm.OpcodeEnd,
   486  					},
   487  				},
   488  				{Body: []byte{
   489  					wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   490  					wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   491  					wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   492  					wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   493  					wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   494  					wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   495  					wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   496  					wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   497  					wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   498  					wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   499  					wasm.OpcodeEnd,
   500  				}},
   501  			},
   502  		},
   503  	}
   504  	ManyParamsSmallResults = TestCase{
   505  		Name: "many_params_small_results",
   506  		Module: SingleFunctionModule(wasm.FunctionType{
   507  			Params: []wasm.ValueType{
   508  				i32, i64, f32, f64, i32, i64, f32, f64,
   509  				i32, i64, f32, f64, i32, i64, f32, f64,
   510  				i32, i64, f32, f64, i32, i64, f32, f64,
   511  				i32, i64, f32, f64, i32, i64, f32, f64,
   512  				i32, i64, f32, f64, i32, i64, f32, f64,
   513  			},
   514  			Results: []wasm.ValueType{
   515  				i32, i64, f32, f64,
   516  			},
   517  		}, []byte{
   518  			wasm.OpcodeLocalGet, 0,
   519  			wasm.OpcodeLocalGet, 9,
   520  			wasm.OpcodeLocalGet, 18,
   521  			wasm.OpcodeLocalGet, 27,
   522  			wasm.OpcodeEnd,
   523  		}, nil),
   524  	}
   525  	SmallParamsManyResults = TestCase{
   526  		Name: "small_params_many_results",
   527  		Module: SingleFunctionModule(wasm.FunctionType{
   528  			Params: []wasm.ValueType{i32, i64, f32, f64},
   529  			Results: []wasm.ValueType{
   530  				i32, i64, f32, f64, i32, i64, f32, f64,
   531  				i32, i64, f32, f64, i32, i64, f32, f64,
   532  				i32, i64, f32, f64, i32, i64, f32, f64,
   533  				i32, i64, f32, f64, i32, i64, f32, f64,
   534  				i32, i64, f32, f64, i32, i64, f32, f64,
   535  			},
   536  		}, []byte{
   537  			wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3, wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   538  			wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3, wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   539  			wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3, wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   540  			wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3, wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   541  			wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3, wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 3,
   542  			wasm.OpcodeEnd,
   543  		}, nil),
   544  	}
   545  	ManyParamsManyResults = TestCase{
   546  		Name: "many_params_many_results",
   547  		Module: SingleFunctionModule(wasm.FunctionType{
   548  			Params: []wasm.ValueType{
   549  				i32, i64, f32, f64, i32, i64, f32, f64,
   550  				i32, i64, f32, f64, i32, i64, f32, f64,
   551  				i32, i64, f32, f64, i32, i64, f32, f64,
   552  				i32, i64, f32, f64, i32, i64, f32, f64,
   553  				i32, i64, f32, f64, i32, i64, f32, f64,
   554  			},
   555  			Results: []wasm.ValueType{
   556  				f64, f32, i64, i32, f64, f32, i64, i32,
   557  				f64, f32, i64, i32, f64, f32, i64, i32,
   558  				f64, f32, i64, i32, f64, f32, i64, i32,
   559  				f64, f32, i64, i32, f64, f32, i64, i32,
   560  				f64, f32, i64, i32, f64, f32, i64, i32,
   561  			},
   562  		}, []byte{
   563  			wasm.OpcodeLocalGet, 39, wasm.OpcodeLocalGet, 38, wasm.OpcodeLocalGet, 37, wasm.OpcodeLocalGet, 36,
   564  			wasm.OpcodeLocalGet, 35, wasm.OpcodeLocalGet, 34, wasm.OpcodeLocalGet, 33, wasm.OpcodeLocalGet, 32,
   565  			wasm.OpcodeLocalGet, 31, wasm.OpcodeLocalGet, 30, wasm.OpcodeLocalGet, 29, wasm.OpcodeLocalGet, 28,
   566  			wasm.OpcodeLocalGet, 27, wasm.OpcodeLocalGet, 26, wasm.OpcodeLocalGet, 25, wasm.OpcodeLocalGet, 24,
   567  			wasm.OpcodeLocalGet, 23, wasm.OpcodeLocalGet, 22, wasm.OpcodeLocalGet, 21, wasm.OpcodeLocalGet, 20,
   568  			wasm.OpcodeLocalGet, 19, wasm.OpcodeLocalGet, 18, wasm.OpcodeLocalGet, 17, wasm.OpcodeLocalGet, 16,
   569  			wasm.OpcodeLocalGet, 15, wasm.OpcodeLocalGet, 14, wasm.OpcodeLocalGet, 13, wasm.OpcodeLocalGet, 12,
   570  			wasm.OpcodeLocalGet, 11, wasm.OpcodeLocalGet, 10, wasm.OpcodeLocalGet, 9, wasm.OpcodeLocalGet, 8,
   571  			wasm.OpcodeLocalGet, 7, wasm.OpcodeLocalGet, 6, wasm.OpcodeLocalGet, 5, wasm.OpcodeLocalGet, 4,
   572  			wasm.OpcodeLocalGet, 3, wasm.OpcodeLocalGet, 2, wasm.OpcodeLocalGet, 1, wasm.OpcodeLocalGet, 0,
   573  			wasm.OpcodeEnd,
   574  		}, nil),
   575  	}
   576  	IntegerComparisons = TestCase{
   577  		Name: "integer_comparisons",
   578  		Module: SingleFunctionModule(wasm.FunctionType{
   579  			Params:  []wasm.ValueType{i32, i32, i64, i64},
   580  			Results: []wasm.ValueType{i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32},
   581  		}, []byte{
   582  			// eq.
   583  			wasm.OpcodeLocalGet, 0,
   584  			wasm.OpcodeLocalGet, 1,
   585  			wasm.OpcodeI32Eq,
   586  			wasm.OpcodeLocalGet, 2,
   587  			wasm.OpcodeLocalGet, 3,
   588  			wasm.OpcodeI64Eq,
   589  			// neq.
   590  			wasm.OpcodeLocalGet, 0,
   591  			wasm.OpcodeLocalGet, 1,
   592  			wasm.OpcodeI32Ne,
   593  			wasm.OpcodeLocalGet, 2,
   594  			wasm.OpcodeLocalGet, 3,
   595  			wasm.OpcodeI64Ne,
   596  			// LtS.
   597  			wasm.OpcodeLocalGet, 0,
   598  			wasm.OpcodeLocalGet, 1,
   599  			wasm.OpcodeI32LtS,
   600  			wasm.OpcodeLocalGet, 2,
   601  			wasm.OpcodeLocalGet, 3,
   602  			wasm.OpcodeI64LtS,
   603  			// LtU.
   604  			wasm.OpcodeLocalGet, 0,
   605  			wasm.OpcodeLocalGet, 1,
   606  			wasm.OpcodeI32LtU,
   607  			wasm.OpcodeLocalGet, 2,
   608  			wasm.OpcodeLocalGet, 3,
   609  			wasm.OpcodeI64LtU,
   610  			// GtS.
   611  			wasm.OpcodeLocalGet, 0,
   612  			wasm.OpcodeLocalGet, 1,
   613  			wasm.OpcodeI32GtS,
   614  			wasm.OpcodeLocalGet, 2,
   615  			wasm.OpcodeLocalGet, 3,
   616  			wasm.OpcodeI64GtS,
   617  			// GtU.
   618  			wasm.OpcodeLocalGet, 0,
   619  			wasm.OpcodeLocalGet, 1,
   620  			wasm.OpcodeI32GtU,
   621  			wasm.OpcodeLocalGet, 2,
   622  			wasm.OpcodeLocalGet, 3,
   623  			wasm.OpcodeI64GtU,
   624  			// LeS.
   625  			wasm.OpcodeLocalGet, 0,
   626  			wasm.OpcodeLocalGet, 1,
   627  			wasm.OpcodeI32LeS,
   628  			wasm.OpcodeLocalGet, 2,
   629  			wasm.OpcodeLocalGet, 3,
   630  			wasm.OpcodeI64LeS,
   631  			// LeU.
   632  			wasm.OpcodeLocalGet, 0,
   633  			wasm.OpcodeLocalGet, 1,
   634  			wasm.OpcodeI32LeU,
   635  			wasm.OpcodeLocalGet, 2,
   636  			wasm.OpcodeLocalGet, 3,
   637  			wasm.OpcodeI64LeU,
   638  			// GeS.
   639  			wasm.OpcodeLocalGet, 0,
   640  			wasm.OpcodeLocalGet, 1,
   641  			wasm.OpcodeI32GeS,
   642  			wasm.OpcodeLocalGet, 2,
   643  			wasm.OpcodeLocalGet, 3,
   644  			wasm.OpcodeI64GeS,
   645  			// GeU.
   646  			wasm.OpcodeLocalGet, 0,
   647  			wasm.OpcodeLocalGet, 1,
   648  			wasm.OpcodeI32GeU,
   649  			wasm.OpcodeLocalGet, 2,
   650  			wasm.OpcodeLocalGet, 3,
   651  			wasm.OpcodeI64GeU,
   652  			wasm.OpcodeEnd,
   653  		}, []wasm.ValueType{}),
   654  	}
   655  	IntegerBitwise = TestCase{
   656  		Name: "integer_bitwise",
   657  		Module: SingleFunctionModule(wasm.FunctionType{
   658  			Params:  []wasm.ValueType{i32, i32, i64, i64},
   659  			Results: []wasm.ValueType{i32, i32, i32, i32, i64, i64, i64, i64, i64, i64},
   660  		}, []byte{
   661  			wasm.OpcodeLocalGet, 0,
   662  			wasm.OpcodeLocalGet, 1,
   663  			wasm.OpcodeI32And,
   664  
   665  			wasm.OpcodeLocalGet, 0,
   666  			wasm.OpcodeLocalGet, 1,
   667  			wasm.OpcodeI32Or,
   668  
   669  			wasm.OpcodeLocalGet, 0,
   670  			wasm.OpcodeLocalGet, 1,
   671  			wasm.OpcodeI32Xor,
   672  
   673  			wasm.OpcodeLocalGet, 0,
   674  			wasm.OpcodeLocalGet, 1,
   675  			wasm.OpcodeI32Rotr,
   676  
   677  			wasm.OpcodeLocalGet, 2,
   678  			wasm.OpcodeLocalGet, 3,
   679  			wasm.OpcodeI64And,
   680  
   681  			wasm.OpcodeLocalGet, 2,
   682  			wasm.OpcodeLocalGet, 3,
   683  			wasm.OpcodeI64Or,
   684  
   685  			wasm.OpcodeLocalGet, 2,
   686  			wasm.OpcodeLocalGet, 3,
   687  			wasm.OpcodeI64Xor,
   688  
   689  			wasm.OpcodeLocalGet, 2,
   690  			wasm.OpcodeLocalGet, 3,
   691  			wasm.OpcodeI64Const, 8,
   692  			wasm.OpcodeI64Shl,
   693  			wasm.OpcodeI64Xor,
   694  
   695  			wasm.OpcodeLocalGet, 2,
   696  			wasm.OpcodeLocalGet, 3,
   697  			wasm.OpcodeI64Rotl,
   698  
   699  			wasm.OpcodeLocalGet, 2,
   700  			wasm.OpcodeLocalGet, 3,
   701  			wasm.OpcodeI64Rotr,
   702  
   703  			wasm.OpcodeEnd,
   704  		}, []wasm.ValueType{}),
   705  	}
   706  	IntegerShift = TestCase{
   707  		Name: "integer_shift",
   708  		Module: SingleFunctionModule(wasm.FunctionType{
   709  			Params:  []wasm.ValueType{i32, i32, i64, i64},
   710  			Results: []wasm.ValueType{i32, i32, i64, i64, i32, i32, i64, i64, i32, i32, i64, i64},
   711  		}, []byte{
   712  			// logical left.
   713  			wasm.OpcodeLocalGet, 0,
   714  			wasm.OpcodeLocalGet, 1,
   715  			wasm.OpcodeI32Shl,
   716  			wasm.OpcodeLocalGet, 0,
   717  			wasm.OpcodeI32Const, 31,
   718  			wasm.OpcodeI32Shl,
   719  			wasm.OpcodeLocalGet, 2,
   720  			wasm.OpcodeLocalGet, 3,
   721  			wasm.OpcodeI64Shl,
   722  			wasm.OpcodeLocalGet, 2,
   723  			wasm.OpcodeI64Const, 32,
   724  			wasm.OpcodeI64Shl,
   725  			// logical right.
   726  			wasm.OpcodeLocalGet, 0,
   727  			wasm.OpcodeLocalGet, 1,
   728  			wasm.OpcodeI32ShrU,
   729  			wasm.OpcodeLocalGet, 0,
   730  			wasm.OpcodeI32Const, 31,
   731  			wasm.OpcodeI32ShrU,
   732  			wasm.OpcodeLocalGet, 2,
   733  			wasm.OpcodeLocalGet, 3,
   734  			wasm.OpcodeI64ShrU,
   735  			wasm.OpcodeLocalGet, 2,
   736  			wasm.OpcodeI64Const, 32,
   737  			wasm.OpcodeI64ShrU,
   738  			// arithmetic right.
   739  			wasm.OpcodeLocalGet, 0,
   740  			wasm.OpcodeLocalGet, 1,
   741  			wasm.OpcodeI32ShrS,
   742  			wasm.OpcodeLocalGet, 0,
   743  			wasm.OpcodeI32Const, 31,
   744  			wasm.OpcodeI32ShrS,
   745  			wasm.OpcodeLocalGet, 2,
   746  			wasm.OpcodeLocalGet, 3,
   747  			wasm.OpcodeI64ShrS,
   748  			wasm.OpcodeLocalGet, 2,
   749  			wasm.OpcodeI64Const, 32,
   750  			wasm.OpcodeI64ShrS,
   751  			wasm.OpcodeEnd,
   752  		}, []wasm.ValueType{}),
   753  	}
   754  	IntegerExtensions = TestCase{
   755  		Name: "integer_extensions",
   756  		Module: SingleFunctionModule(wasm.FunctionType{
   757  			Params:  []wasm.ValueType{i32, i64},
   758  			Results: []wasm.ValueType{i64, i64, i64, i64, i64, i32, i32},
   759  		}, []byte{
   760  			wasm.OpcodeLocalGet, 0,
   761  			wasm.OpcodeI64ExtendI32S,
   762  
   763  			wasm.OpcodeLocalGet, 0,
   764  			wasm.OpcodeI64ExtendI32U,
   765  
   766  			wasm.OpcodeLocalGet, 1,
   767  			wasm.OpcodeI64Extend8S,
   768  
   769  			wasm.OpcodeLocalGet, 1,
   770  			wasm.OpcodeI64Extend16S,
   771  
   772  			wasm.OpcodeLocalGet, 1,
   773  			wasm.OpcodeI64Extend32S,
   774  
   775  			wasm.OpcodeLocalGet, 0,
   776  			wasm.OpcodeI32Extend8S,
   777  
   778  			wasm.OpcodeLocalGet, 0,
   779  			wasm.OpcodeI32Extend16S,
   780  
   781  			wasm.OpcodeEnd,
   782  		}, []wasm.ValueType{}),
   783  	}
   784  	IntegerBitCounts = TestCase{
   785  		Name: "integer_bit_counts",
   786  		Module: SingleFunctionModule(wasm.FunctionType{
   787  			Params:  []wasm.ValueType{i32, i64},
   788  			Results: []wasm.ValueType{i32, i32, i32, i64, i64, i64},
   789  		}, []byte{
   790  			wasm.OpcodeLocalGet, 0,
   791  			wasm.OpcodeI32Clz,
   792  
   793  			wasm.OpcodeLocalGet, 0,
   794  			wasm.OpcodeI32Ctz,
   795  
   796  			wasm.OpcodeLocalGet, 0,
   797  			wasm.OpcodeI32Popcnt,
   798  
   799  			wasm.OpcodeLocalGet, 1,
   800  			wasm.OpcodeI64Clz,
   801  
   802  			wasm.OpcodeLocalGet, 1,
   803  			wasm.OpcodeI64Ctz,
   804  
   805  			wasm.OpcodeLocalGet, 1,
   806  			wasm.OpcodeI64Popcnt,
   807  
   808  			wasm.OpcodeEnd,
   809  		}, []wasm.ValueType{}),
   810  	}
   811  	FloatComparisons = TestCase{
   812  		Name: "float_comparisons",
   813  		Module: SingleFunctionModule(wasm.FunctionType{
   814  			Params:  []wasm.ValueType{f32, f32, f64, f64},
   815  			Results: []wasm.ValueType{i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32},
   816  		}, []byte{
   817  			wasm.OpcodeLocalGet, 0,
   818  			wasm.OpcodeLocalGet, 1,
   819  			wasm.OpcodeF32Eq,
   820  			wasm.OpcodeLocalGet, 0,
   821  			wasm.OpcodeLocalGet, 1,
   822  			wasm.OpcodeF32Ne,
   823  			wasm.OpcodeLocalGet, 0,
   824  			wasm.OpcodeLocalGet, 1,
   825  			wasm.OpcodeF32Lt,
   826  			wasm.OpcodeLocalGet, 0,
   827  			wasm.OpcodeLocalGet, 1,
   828  			wasm.OpcodeF32Gt,
   829  			wasm.OpcodeLocalGet, 0,
   830  			wasm.OpcodeLocalGet, 1,
   831  			wasm.OpcodeF32Le,
   832  			wasm.OpcodeLocalGet, 0,
   833  			wasm.OpcodeLocalGet, 1,
   834  			wasm.OpcodeF32Ge,
   835  
   836  			wasm.OpcodeLocalGet, 2,
   837  			wasm.OpcodeLocalGet, 3,
   838  			wasm.OpcodeF64Eq,
   839  			wasm.OpcodeLocalGet, 2,
   840  			wasm.OpcodeLocalGet, 3,
   841  			wasm.OpcodeF64Ne,
   842  			wasm.OpcodeLocalGet, 2,
   843  			wasm.OpcodeLocalGet, 3,
   844  			wasm.OpcodeF64Lt,
   845  			wasm.OpcodeLocalGet, 2,
   846  			wasm.OpcodeLocalGet, 3,
   847  			wasm.OpcodeF64Gt,
   848  			wasm.OpcodeLocalGet, 2,
   849  			wasm.OpcodeLocalGet, 3,
   850  			wasm.OpcodeF64Le,
   851  			wasm.OpcodeLocalGet, 2,
   852  			wasm.OpcodeLocalGet, 3,
   853  			wasm.OpcodeF64Ge,
   854  
   855  			wasm.OpcodeEnd,
   856  		}, []wasm.ValueType{}),
   857  	}
   858  	FloatConversions = TestCase{
   859  		Name: "float_conversions",
   860  		Module: SingleFunctionModule(wasm.FunctionType{
   861  			Params:  []wasm.ValueType{f64, f32},
   862  			Results: []wasm.ValueType{i64, i64, i32, i32, i64, i64, i32, i32, f32, f64},
   863  		}, []byte{
   864  			wasm.OpcodeLocalGet, 0,
   865  			wasm.OpcodeI64TruncF64S,
   866  
   867  			wasm.OpcodeLocalGet, 1,
   868  			wasm.OpcodeI64TruncF32S,
   869  
   870  			wasm.OpcodeLocalGet, 0,
   871  			wasm.OpcodeI32TruncF64S,
   872  
   873  			wasm.OpcodeLocalGet, 1,
   874  			wasm.OpcodeI32TruncF32S,
   875  
   876  			wasm.OpcodeLocalGet, 0,
   877  			wasm.OpcodeI64TruncF64U,
   878  
   879  			wasm.OpcodeLocalGet, 1,
   880  			wasm.OpcodeI64TruncF32U,
   881  
   882  			wasm.OpcodeLocalGet, 0,
   883  			wasm.OpcodeI32TruncF64U,
   884  
   885  			wasm.OpcodeLocalGet, 1,
   886  			wasm.OpcodeI32TruncF32U,
   887  
   888  			wasm.OpcodeLocalGet, 0,
   889  			wasm.OpcodeF32DemoteF64,
   890  
   891  			wasm.OpcodeLocalGet, 1,
   892  			wasm.OpcodeF64PromoteF32,
   893  
   894  			wasm.OpcodeEnd,
   895  		}, []wasm.ValueType{}),
   896  	}
   897  	NonTrappingFloatConversions = TestCase{
   898  		Name: "float_conversions",
   899  		Module: SingleFunctionModule(wasm.FunctionType{
   900  			Params:  []wasm.ValueType{f64, f32},
   901  			Results: []wasm.ValueType{i64, i64, i32, i32, i64, i64, i32, i32},
   902  		}, []byte{
   903  			wasm.OpcodeLocalGet, 0,
   904  			wasm.OpcodeMiscPrefix, wasm.OpcodeMiscI64TruncSatF64S,
   905  
   906  			wasm.OpcodeLocalGet, 1,
   907  			wasm.OpcodeMiscPrefix, wasm.OpcodeMiscI64TruncSatF32S,
   908  
   909  			wasm.OpcodeLocalGet, 0,
   910  			wasm.OpcodeMiscPrefix, wasm.OpcodeMiscI32TruncSatF64S,
   911  
   912  			wasm.OpcodeLocalGet, 1,
   913  			wasm.OpcodeMiscPrefix, wasm.OpcodeMiscI32TruncSatF32S,
   914  
   915  			wasm.OpcodeLocalGet, 0,
   916  			wasm.OpcodeMiscPrefix, wasm.OpcodeMiscI64TruncSatF64U,
   917  
   918  			wasm.OpcodeLocalGet, 1,
   919  			wasm.OpcodeMiscPrefix, wasm.OpcodeMiscI64TruncSatF32U,
   920  
   921  			wasm.OpcodeLocalGet, 0,
   922  			wasm.OpcodeMiscPrefix, wasm.OpcodeMiscI32TruncSatF64U,
   923  
   924  			wasm.OpcodeLocalGet, 1,
   925  			wasm.OpcodeMiscPrefix, wasm.OpcodeMiscI32TruncSatF32U,
   926  
   927  			wasm.OpcodeEnd,
   928  		}, []wasm.ValueType{}),
   929  	}
   930  	FibonacciRecursive = TestCase{
   931  		Name: "recursive_fibonacci",
   932  		Module: SingleFunctionModule(i32_i32, []byte{
   933  			wasm.OpcodeLocalGet, 0,
   934  			wasm.OpcodeI32Const, 2,
   935  			wasm.OpcodeI32LtS,
   936  			wasm.OpcodeIf, blockSignature_vv,
   937  			wasm.OpcodeLocalGet, 0,
   938  			wasm.OpcodeReturn,
   939  			wasm.OpcodeEnd,
   940  			wasm.OpcodeLocalGet, 0,
   941  			wasm.OpcodeI32Const, 1,
   942  			wasm.OpcodeI32Sub,
   943  			wasm.OpcodeCall, 0,
   944  			wasm.OpcodeLocalGet, 0,
   945  			wasm.OpcodeI32Const, 2,
   946  			wasm.OpcodeI32Sub,
   947  			wasm.OpcodeCall, 0,
   948  			wasm.OpcodeI32Add,
   949  			wasm.OpcodeEnd,
   950  		}, nil),
   951  	}
   952  	ImportedFunctionCall = TestCase{
   953  		Name: "imported_function_call",
   954  		Imported: &wasm.Module{
   955  			ExportSection:   []wasm.Export{{Name: "i32_i32", Type: wasm.ExternTypeFunc}},
   956  			TypeSection:     []wasm.FunctionType{i32i32_i32},
   957  			FunctionSection: []wasm.Index{0},
   958  			CodeSection: []wasm.Code{{Body: []byte{
   959  				wasm.OpcodeLocalGet, 0,
   960  				wasm.OpcodeLocalGet, 1,
   961  				wasm.OpcodeI32Mul,
   962  				wasm.OpcodeEnd,
   963  			}}},
   964  			NameSection: &wasm.NameSection{ModuleName: "env"},
   965  		},
   966  		Module: &wasm.Module{
   967  			ImportFunctionCount: 1,
   968  			TypeSection:         []wasm.FunctionType{i32_i32, i32i32_i32},
   969  			ImportSection:       []wasm.Import{{Type: wasm.ExternTypeFunc, Module: "env", Name: "i32_i32", DescFunc: 1}},
   970  			FunctionSection:     []wasm.Index{0},
   971  			ExportSection: []wasm.Export{
   972  				{Name: ExportedFunctionName, Type: wasm.ExternTypeFunc, Index: 1},
   973  				{Name: "imported_exported", Type: wasm.ExternTypeFunc, Index: 0 /* imported */},
   974  			},
   975  			CodeSection: []wasm.Code{{Body: []byte{
   976  				wasm.OpcodeLocalGet, 0,
   977  				wasm.OpcodeLocalGet, 0,
   978  				wasm.OpcodeCall, 0,
   979  				wasm.OpcodeEnd,
   980  			}}},
   981  		},
   982  	}
   983  
   984  	MemoryStoreBasic = TestCase{
   985  		Name: "memory_load_basic",
   986  		Module: &wasm.Module{
   987  			TypeSection:     []wasm.FunctionType{{Params: []wasm.ValueType{i32, i32}, Results: []wasm.ValueType{i32}}},
   988  			ExportSection:   []wasm.Export{{Name: ExportedFunctionName, Type: wasm.ExternTypeFunc, Index: 0}},
   989  			MemorySection:   &wasm.Memory{Min: 1},
   990  			FunctionSection: []wasm.Index{0},
   991  			CodeSection: []wasm.Code{{Body: []byte{
   992  				wasm.OpcodeLocalGet, 0, // offset
   993  				wasm.OpcodeLocalGet, 1, // value
   994  				wasm.OpcodeI32Store, 0x2, 0x0, // alignment=2 (natural alignment) staticOffset=0
   995  				// Read back.
   996  				wasm.OpcodeLocalGet, 0, // offset
   997  				wasm.OpcodeI32Load, 0x2, 0x0, // alignment=2 (natural alignment) staticOffset=0
   998  				wasm.OpcodeEnd,
   999  			}}},
  1000  		},
  1001  	}
  1002  
  1003  	MemoryStores = TestCase{
  1004  		Name: "memory_load_basic",
  1005  		Module: &wasm.Module{
  1006  			TypeSection:     []wasm.FunctionType{{Params: []wasm.ValueType{i32, i64, f32, f64}}},
  1007  			ExportSection:   []wasm.Export{{Name: ExportedFunctionName, Type: wasm.ExternTypeFunc, Index: 0}},
  1008  			MemorySection:   &wasm.Memory{Min: 1},
  1009  			FunctionSection: []wasm.Index{0},
  1010  			CodeSection: []wasm.Code{{Body: []byte{
  1011  				wasm.OpcodeI32Const, 0, // offset
  1012  				wasm.OpcodeLocalGet, 0, // value
  1013  				wasm.OpcodeI32Store, 0x2, 0x0,
  1014  
  1015  				wasm.OpcodeI32Const, 8, // offset
  1016  				wasm.OpcodeLocalGet, 1, // value
  1017  				wasm.OpcodeI64Store, 0x3, 0x0,
  1018  
  1019  				wasm.OpcodeI32Const, 16, // offset
  1020  				wasm.OpcodeLocalGet, 2, // value
  1021  				wasm.OpcodeF32Store, 0x2, 0x0,
  1022  
  1023  				wasm.OpcodeI32Const, 24, // offset
  1024  				wasm.OpcodeLocalGet, 3, // value
  1025  				wasm.OpcodeF64Store, 0x3, 0x0,
  1026  
  1027  				wasm.OpcodeI32Const, 32,
  1028  				wasm.OpcodeLocalGet, 0, // value
  1029  				wasm.OpcodeI32Store8, 0x0, 0,
  1030  
  1031  				wasm.OpcodeI32Const, 40,
  1032  				wasm.OpcodeLocalGet, 0, // value
  1033  				wasm.OpcodeI32Store16, 0x1, 0,
  1034  
  1035  				wasm.OpcodeI32Const, 48,
  1036  				wasm.OpcodeLocalGet, 1, // value
  1037  				wasm.OpcodeI64Store8, 0x0, 0,
  1038  
  1039  				wasm.OpcodeI32Const, 56,
  1040  				wasm.OpcodeLocalGet, 1, // value
  1041  				wasm.OpcodeI64Store16, 0x1, 0,
  1042  
  1043  				wasm.OpcodeI32Const, 0xc0, 0, // 64 in leb128.
  1044  				wasm.OpcodeLocalGet, 1, // value
  1045  				wasm.OpcodeI64Store32, 0x2, 0,
  1046  
  1047  				wasm.OpcodeEnd,
  1048  			}}},
  1049  		},
  1050  	}
  1051  
  1052  	MemoryLoadBasic = TestCase{
  1053  		Name: "memory_load_basic",
  1054  		Module: &wasm.Module{
  1055  			TypeSection: []wasm.FunctionType{{
  1056  				Params:  []wasm.ValueType{i32},
  1057  				Results: []wasm.ValueType{i32},
  1058  			}},
  1059  			ExportSection:   []wasm.Export{{Name: ExportedFunctionName, Type: wasm.ExternTypeFunc, Index: 0}},
  1060  			MemorySection:   &wasm.Memory{Min: 1},
  1061  			FunctionSection: []wasm.Index{0},
  1062  			CodeSection: []wasm.Code{{Body: []byte{
  1063  				wasm.OpcodeLocalGet, 0,
  1064  				wasm.OpcodeI32Load, 0x2, 0x0, // alignment=2 (natural alignment) staticOffset=0
  1065  				wasm.OpcodeEnd,
  1066  			}}},
  1067  			DataSection: []wasm.DataSegment{{OffsetExpression: constExprI32(0), Init: maskedBuf(int(wasm.MemoryPageSize))}},
  1068  		},
  1069  	}
  1070  
  1071  	MemorySizeGrow = TestCase{
  1072  		Name: "memory_size_grow",
  1073  		Module: &wasm.Module{
  1074  			TypeSection:     []wasm.FunctionType{{Results: []wasm.ValueType{i32, i32, i32}}},
  1075  			ExportSection:   []wasm.Export{{Name: ExportedFunctionName, Type: wasm.ExternTypeFunc, Index: 0}},
  1076  			MemorySection:   &wasm.Memory{Min: 1, Max: 2, IsMaxEncoded: true},
  1077  			FunctionSection: []wasm.Index{0},
  1078  			CodeSection: []wasm.Code{{Body: []byte{
  1079  				wasm.OpcodeI32Const, 1,
  1080  				wasm.OpcodeMemoryGrow, 0, // return 1.
  1081  				wasm.OpcodeMemorySize, 0, // return 2.
  1082  				wasm.OpcodeI32Const, 1,
  1083  				wasm.OpcodeMemoryGrow, 0, // return -1 since already maximum size.
  1084  				wasm.OpcodeEnd,
  1085  			}}},
  1086  		},
  1087  	}
  1088  
  1089  	MemoryLoadBasic2 = TestCase{
  1090  		Name: "memory_load_basic2",
  1091  		Module: &wasm.Module{
  1092  			TypeSection:     []wasm.FunctionType{i32_i32, {}},
  1093  			ExportSection:   []wasm.Export{{Name: ExportedFunctionName, Type: wasm.ExternTypeFunc, Index: 0}},
  1094  			MemorySection:   &wasm.Memory{Min: 1},
  1095  			FunctionSection: []wasm.Index{0, 1},
  1096  			CodeSection: []wasm.Code{
  1097  				{Body: []byte{
  1098  					wasm.OpcodeLocalGet, 0,
  1099  					wasm.OpcodeI32Const, 0,
  1100  					wasm.OpcodeI32Eq,
  1101  					wasm.OpcodeIf, blockSignature_vv,
  1102  					wasm.OpcodeCall, 0x1, // After this the memory buf/size pointer reloads.
  1103  					wasm.OpcodeElse, // But in Else block, we do nothing, so not reloaded.
  1104  					wasm.OpcodeEnd,
  1105  
  1106  					// Therefore, this block should reload the memory buf/size pointer here.
  1107  					wasm.OpcodeLocalGet, 0,
  1108  					wasm.OpcodeI32Load, 0x2, 0x0, // alignment=2 (natural alignment) staticOffset=0
  1109  
  1110  					wasm.OpcodeEnd,
  1111  				}},
  1112  				{Body: []byte{wasm.OpcodeEnd}},
  1113  			},
  1114  			DataSection: []wasm.DataSegment{{OffsetExpression: constExprI32(0), Init: maskedBuf(int(wasm.MemoryPageSize))}},
  1115  		},
  1116  	}
  1117  
  1118  	ImportedMemoryGrow = TestCase{
  1119  		Name: "imported_memory_grow",
  1120  		Imported: &wasm.Module{
  1121  			ExportSection: []wasm.Export{
  1122  				{Name: "mem", Type: wasm.ExternTypeMemory, Index: 0},
  1123  				{Name: "size", Type: wasm.ExternTypeFunc, Index: 0},
  1124  			},
  1125  			MemorySection:   &wasm.Memory{Min: 1},
  1126  			TypeSection:     []wasm.FunctionType{v_i32},
  1127  			FunctionSection: []wasm.Index{0},
  1128  			CodeSection:     []wasm.Code{{Body: []byte{wasm.OpcodeMemorySize, 0, wasm.OpcodeEnd}}},
  1129  			DataSection:     []wasm.DataSegment{{OffsetExpression: constExprI32(0), Init: maskedBuf(int(wasm.MemoryPageSize))}},
  1130  			NameSection:     &wasm.NameSection{ModuleName: "env"},
  1131  		},
  1132  		Module: &wasm.Module{
  1133  			ImportMemoryCount:   1,
  1134  			ImportFunctionCount: 1,
  1135  			ImportSection: []wasm.Import{
  1136  				{Module: "env", Name: "mem", Type: wasm.ExternTypeMemory, DescMem: &wasm.Memory{Min: 1}},
  1137  				{Module: "env", Name: "size", Type: wasm.ExternTypeFunc, DescFunc: 0},
  1138  			},
  1139  			TypeSection:     []wasm.FunctionType{v_i32, {Results: []wasm.ValueType{i32, i32, i32, i32}}},
  1140  			ExportSection:   []wasm.Export{{Name: ExportedFunctionName, Type: wasm.ExternTypeFunc, Index: 1}},
  1141  			FunctionSection: []wasm.Index{1},
  1142  			CodeSection: []wasm.Code{
  1143  				{Body: []byte{
  1144  					wasm.OpcodeCall, 0, // Call imported size function. --> 1
  1145  					wasm.OpcodeMemorySize, 0, // --> 1.
  1146  					wasm.OpcodeI32Const, 10,
  1147  					wasm.OpcodeMemoryGrow, 0,
  1148  					wasm.OpcodeDrop,
  1149  					wasm.OpcodeCall, 0, // Call imported size function. --> 11.
  1150  					wasm.OpcodeMemorySize, 0, // --> 11.
  1151  					wasm.OpcodeEnd,
  1152  				}},
  1153  			},
  1154  		},
  1155  	}
  1156  
  1157  	GlobalsGet = TestCase{
  1158  		Name: "globals_get",
  1159  		Module: &wasm.Module{
  1160  			TypeSection:     []wasm.FunctionType{{Results: []wasm.ValueType{i32, i64, f32, f64}}},
  1161  			ExportSection:   []wasm.Export{{Name: ExportedFunctionName, Type: wasm.ExternTypeFunc, Index: 0}},
  1162  			FunctionSection: []wasm.Index{0},
  1163  			GlobalSection: []wasm.Global{
  1164  				{
  1165  					Type: wasm.GlobalType{ValType: wasm.ValueTypeI32, Mutable: false},
  1166  					Init: constExprI32(math.MinInt32),
  1167  				},
  1168  				{
  1169  					Type: wasm.GlobalType{ValType: wasm.ValueTypeI64, Mutable: false},
  1170  					Init: constExprI64(math.MinInt64),
  1171  				},
  1172  				{
  1173  					Type: wasm.GlobalType{ValType: wasm.ValueTypeF32, Mutable: false},
  1174  					Init: constExprF32(math.MaxFloat32),
  1175  				},
  1176  				{
  1177  					Type: wasm.GlobalType{ValType: wasm.ValueTypeF64, Mutable: false},
  1178  					Init: constExprF64(math.MaxFloat64),
  1179  				},
  1180  			},
  1181  			CodeSection: []wasm.Code{
  1182  				{Body: []byte{
  1183  					wasm.OpcodeGlobalGet, 0,
  1184  					wasm.OpcodeGlobalGet, 1,
  1185  					wasm.OpcodeGlobalGet, 2,
  1186  					wasm.OpcodeGlobalGet, 3,
  1187  					wasm.OpcodeEnd,
  1188  				}},
  1189  			},
  1190  		},
  1191  	}
  1192  
  1193  	GlobalsSet = TestCase{
  1194  		Name: "globals_get",
  1195  		Module: &wasm.Module{
  1196  			TypeSection:     []wasm.FunctionType{{Results: []wasm.ValueType{i32, i64, f32, f64}}},
  1197  			ExportSection:   []wasm.Export{{Name: ExportedFunctionName, Type: wasm.ExternTypeFunc, Index: 0}},
  1198  			FunctionSection: []wasm.Index{0},
  1199  			GlobalSection: []wasm.Global{
  1200  				{
  1201  					Type: wasm.GlobalType{ValType: wasm.ValueTypeI32, Mutable: true},
  1202  					Init: constExprI32(0),
  1203  				},
  1204  				{
  1205  					Type: wasm.GlobalType{ValType: wasm.ValueTypeI64, Mutable: true},
  1206  					Init: constExprI64(0),
  1207  				},
  1208  				{
  1209  					Type: wasm.GlobalType{ValType: wasm.ValueTypeF32, Mutable: true},
  1210  					Init: constExprF32(0),
  1211  				},
  1212  				{
  1213  					Type: wasm.GlobalType{ValType: wasm.ValueTypeF64, Mutable: true},
  1214  					Init: constExprF64(0),
  1215  				},
  1216  			},
  1217  			CodeSection: []wasm.Code{
  1218  				{Body: []byte{
  1219  					wasm.OpcodeI32Const, 1,
  1220  					wasm.OpcodeGlobalSet, 0,
  1221  					wasm.OpcodeGlobalGet, 0,
  1222  					wasm.OpcodeI64Const, 2,
  1223  					wasm.OpcodeGlobalSet, 1,
  1224  					wasm.OpcodeGlobalGet, 1,
  1225  					wasm.OpcodeF32Const, 0, 0, 64, 64, // 3.0
  1226  					wasm.OpcodeGlobalSet, 2,
  1227  					wasm.OpcodeGlobalGet, 2,
  1228  					wasm.OpcodeF64Const, 0, 0, 0, 0, 0, 0, 16, 64, // 4.0
  1229  					wasm.OpcodeGlobalSet, 3,
  1230  					wasm.OpcodeGlobalGet, 3,
  1231  					wasm.OpcodeEnd,
  1232  				}},
  1233  			},
  1234  		},
  1235  	}
  1236  
  1237  	GlobalsMutable = TestCase{
  1238  		Module: &wasm.Module{
  1239  			TypeSection: []wasm.FunctionType{
  1240  				{Results: []wasm.ValueType{i32, i64, f32, f64, i32, i64, f32, f64}},
  1241  				{},
  1242  			},
  1243  			ExportSection:   []wasm.Export{{Name: ExportedFunctionName, Type: wasm.ExternTypeFunc, Index: 0}},
  1244  			FunctionSection: []wasm.Index{0, 1},
  1245  			GlobalSection: []wasm.Global{
  1246  				{
  1247  					Type: wasm.GlobalType{ValType: wasm.ValueTypeI32, Mutable: true},
  1248  					Init: constExprI32(100),
  1249  				},
  1250  				{
  1251  					Type: wasm.GlobalType{ValType: wasm.ValueTypeI64, Mutable: true},
  1252  					Init: constExprI64(200),
  1253  				},
  1254  				{
  1255  					Type: wasm.GlobalType{ValType: wasm.ValueTypeF32, Mutable: true},
  1256  					Init: constExprF32(300.0),
  1257  				},
  1258  				{
  1259  					Type: wasm.GlobalType{ValType: wasm.ValueTypeF64, Mutable: true},
  1260  					Init: constExprF64(400.0),
  1261  				},
  1262  			},
  1263  			CodeSection: []wasm.Code{
  1264  				{Body: []byte{
  1265  					wasm.OpcodeGlobalGet, 0,
  1266  					wasm.OpcodeGlobalGet, 1,
  1267  					wasm.OpcodeGlobalGet, 2,
  1268  					wasm.OpcodeGlobalGet, 3,
  1269  					wasm.OpcodeCall, 1,
  1270  					wasm.OpcodeGlobalGet, 0,
  1271  					wasm.OpcodeGlobalGet, 1,
  1272  					wasm.OpcodeGlobalGet, 2,
  1273  					wasm.OpcodeGlobalGet, 3,
  1274  					wasm.OpcodeEnd,
  1275  				}},
  1276  				{Body: []byte{
  1277  					wasm.OpcodeI32Const, 1,
  1278  					wasm.OpcodeGlobalSet, 0,
  1279  					wasm.OpcodeI64Const, 2,
  1280  					wasm.OpcodeGlobalSet, 1,
  1281  					wasm.OpcodeF32Const, 0, 0, 64, 64, // 3.0
  1282  					wasm.OpcodeGlobalSet, 2,
  1283  					wasm.OpcodeF64Const, 0, 0, 0, 0, 0, 0, 16, 64, // 4.0
  1284  					wasm.OpcodeGlobalSet, 3,
  1285  					wasm.OpcodeReturn,
  1286  					wasm.OpcodeEnd,
  1287  				}},
  1288  			},
  1289  		},
  1290  	}
  1291  
  1292  	MemoryLoads = TestCase{
  1293  		Name: "memory_loads",
  1294  		Module: &wasm.Module{
  1295  			TypeSection: []wasm.FunctionType{{
  1296  				Params: []wasm.ValueType{i32},
  1297  				Results: []wasm.ValueType{
  1298  					i32, i64, f32, f64, i32, i64, f32, f64,
  1299  					i32, i32, i32, i32, i32, i32, i32, i32,
  1300  					i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64,
  1301  				},
  1302  			}},
  1303  			ExportSection:   []wasm.Export{{Name: ExportedFunctionName, Type: wasm.ExternTypeFunc, Index: 0}},
  1304  			MemorySection:   &wasm.Memory{Min: 1},
  1305  			FunctionSection: []wasm.Index{0},
  1306  			CodeSection: []wasm.Code{{Body: []byte{
  1307  				// Basic loads (without extensions).
  1308  				wasm.OpcodeLocalGet, 0, // 0
  1309  				wasm.OpcodeI32Load, 0x2, 0x0, // alignment=2 (natural alignment) staticOffset=0
  1310  				wasm.OpcodeLocalGet, 0, // 1
  1311  				wasm.OpcodeI64Load, 0x3, 0x0, // alignment=3 (natural alignment) staticOffset=0
  1312  				wasm.OpcodeLocalGet, 0, // 2
  1313  				wasm.OpcodeF32Load, 0x2, 0x0, // alignment=2 (natural alignment) staticOffset=0
  1314  				wasm.OpcodeLocalGet, 0, // 3
  1315  				wasm.OpcodeF64Load, 0x3, 0x0, // alignment=3 (natural alignment) staticOffset=0
  1316  				wasm.OpcodeLocalGet, 0, // 4
  1317  				wasm.OpcodeI32Load, 0x2, 0xf, // alignment=2 (natural alignment) staticOffset=16
  1318  				wasm.OpcodeLocalGet, 0, // 5
  1319  				wasm.OpcodeI64Load, 0x3, 0xf, // alignment=3 (natural alignment) staticOffset=16
  1320  				wasm.OpcodeLocalGet, 0, // 6
  1321  				wasm.OpcodeF32Load, 0x2, 0xf, // alignment=2 (natural alignment) staticOffset=16
  1322  				wasm.OpcodeLocalGet, 0, // 7
  1323  				wasm.OpcodeF64Load, 0x3, 0xf, // alignment=3 (natural alignment) staticOffset=16
  1324  
  1325  				// Extension integer loads.
  1326  				wasm.OpcodeLocalGet, 0, // 8
  1327  				wasm.OpcodeI32Load8S, 0x0, 0x0, // alignment=0 (natural alignment) staticOffset=0
  1328  				wasm.OpcodeLocalGet, 0, // 9
  1329  				wasm.OpcodeI32Load8S, 0x0, 0xf, // alignment=0 (natural alignment) staticOffset=16
  1330  
  1331  				wasm.OpcodeLocalGet, 0, // 10
  1332  				wasm.OpcodeI32Load8U, 0x0, 0x0, // alignment=0 (natural alignment) staticOffset=0
  1333  				wasm.OpcodeLocalGet, 0, // 11
  1334  				wasm.OpcodeI32Load8U, 0x0, 0xf, // alignment=0 (natural alignment) staticOffset=16
  1335  				wasm.OpcodeLocalGet, 0, // 12
  1336  				wasm.OpcodeI32Load16S, 0x1, 0x0, // alignment=1 (natural alignment) staticOffset=0
  1337  				wasm.OpcodeLocalGet, 0, // 13
  1338  				wasm.OpcodeI32Load16S, 0x1, 0xf, // alignment=1 (natural alignment) staticOffset=16
  1339  				wasm.OpcodeLocalGet, 0, // 14
  1340  				wasm.OpcodeI32Load16U, 0x1, 0x0, // alignment=1 (natural alignment) staticOffset=0
  1341  				wasm.OpcodeLocalGet, 0, // 15
  1342  				wasm.OpcodeI32Load16U, 0x1, 0xf, // alignment=1 (natural alignment) staticOffset=16
  1343  				wasm.OpcodeLocalGet, 0, // 16
  1344  				wasm.OpcodeI64Load8S, 0x0, 0x0, // alignment=0 (natural alignment) staticOffset=0
  1345  				wasm.OpcodeLocalGet, 0, // 17
  1346  				wasm.OpcodeI64Load8S, 0x0, 0xf, // alignment=0 (natural alignment) staticOffset=16
  1347  				wasm.OpcodeLocalGet, 0, // 18
  1348  				wasm.OpcodeI64Load8U, 0x0, 0x0, // alignment=0 (natural alignment) staticOffset=0
  1349  				wasm.OpcodeLocalGet, 0, // 19
  1350  
  1351  				wasm.OpcodeI64Load8U, 0x0, 0xf, // alignment=0 (natural alignment) staticOffset=16
  1352  				wasm.OpcodeLocalGet, 0, // 20
  1353  				wasm.OpcodeI64Load16S, 0x1, 0x0, // alignment=1 (natural alignment) staticOffset=0
  1354  				wasm.OpcodeLocalGet, 0, // 21
  1355  				wasm.OpcodeI64Load16S, 0x1, 0xf, // alignment=1 (natural alignment) staticOffset=16
  1356  				wasm.OpcodeLocalGet, 0, // 22
  1357  				wasm.OpcodeI64Load16U, 0x1, 0x0, // alignment=1 (natural alignment) staticOffset=0
  1358  				wasm.OpcodeLocalGet, 0, // 23
  1359  				wasm.OpcodeI64Load16U, 0x1, 0xf, // alignment=1 (natural alignment) staticOffset=16
  1360  				wasm.OpcodeLocalGet, 0, // 24
  1361  				wasm.OpcodeI64Load32S, 0x2, 0x0, // alignment=2 (natural alignment) staticOffset=0
  1362  				wasm.OpcodeLocalGet, 0, // 25
  1363  				wasm.OpcodeI64Load32S, 0x2, 0xf, // alignment=2 (natural alignment) staticOffset=16
  1364  				wasm.OpcodeLocalGet, 0, // 26
  1365  				wasm.OpcodeI64Load32U, 0x2, 0x0, // alignment=2 (natural alignment) staticOffset=0
  1366  				wasm.OpcodeLocalGet, 0, // 27
  1367  				wasm.OpcodeI64Load32U, 0x2, 0xf, // alignment=2 (natural alignment) staticOffset=16
  1368  
  1369  				wasm.OpcodeEnd,
  1370  			}}},
  1371  			DataSection: []wasm.DataSegment{{OffsetExpression: constExprI32(0), Init: maskedBuf(int(wasm.MemoryPageSize))}},
  1372  		},
  1373  	}
  1374  
  1375  	CallIndirect = TestCase{
  1376  		Module: &wasm.Module{
  1377  			TypeSection:     []wasm.FunctionType{i32_i32, {}, v_i32, v_i32i32},
  1378  			ExportSection:   []wasm.Export{{Name: ExportedFunctionName, Type: wasm.ExternTypeFunc, Index: 0}},
  1379  			FunctionSection: []wasm.Index{0, 1, 2, 3},
  1380  			TableSection:    []wasm.Table{{Type: wasm.RefTypeFuncref, Min: 1000}},
  1381  			ElementSection: []wasm.ElementSegment{
  1382  				{
  1383  					OffsetExpr: constExprI32(0), TableIndex: 0, Type: wasm.RefTypeFuncref, Mode: wasm.ElementModeActive,
  1384  					// Set the function 1, 2, 3 at the beginning of the table.
  1385  					Init: []wasm.Index{1, 2, 3},
  1386  				},
  1387  			},
  1388  			CodeSection: []wasm.Code{
  1389  				{Body: []byte{
  1390  					wasm.OpcodeLocalGet, 0,
  1391  					wasm.OpcodeCallIndirect, 2, 0, // Expecting type 2 (v_i32), in tables[0]
  1392  					wasm.OpcodeEnd,
  1393  				}},
  1394  				{Body: []byte{wasm.OpcodeEnd}},
  1395  				{Body: []byte{wasm.OpcodeI32Const, 10, wasm.OpcodeEnd}},
  1396  				{Body: []byte{wasm.OpcodeI32Const, 1, wasm.OpcodeI32Const, 1, wasm.OpcodeEnd}},
  1397  			},
  1398  		},
  1399  	}
  1400  
  1401  	BrTable = TestCase{
  1402  		Module: &wasm.Module{
  1403  			TypeSection:     []wasm.FunctionType{i32_i32, {}},
  1404  			ExportSection:   []wasm.Export{{Name: ExportedFunctionName, Type: wasm.ExternTypeFunc, Index: 0}},
  1405  			FunctionSection: []wasm.Index{0},
  1406  			CodeSection: []wasm.Code{
  1407  				{Body: []byte{
  1408  					wasm.OpcodeBlock, 1, // Signature v_v,
  1409  					wasm.OpcodeBlock, 1, // Signature v_v,
  1410  					wasm.OpcodeBlock, 1, // Signature v_v,
  1411  					wasm.OpcodeBlock, 1, // Signature v_v,
  1412  					wasm.OpcodeBlock, 1, // Signature v_v,
  1413  					wasm.OpcodeBlock, 1, // Signature v_v,
  1414  					wasm.OpcodeLocalGet, 0,
  1415  					wasm.OpcodeBrTable,
  1416  					6,                // size of label vector
  1417  					0, 1, 2, 3, 4, 5, // labels.
  1418  					0, // default label
  1419  					wasm.OpcodeEnd, wasm.OpcodeI32Const, 11, wasm.OpcodeReturn,
  1420  					wasm.OpcodeEnd, wasm.OpcodeI32Const, 12, wasm.OpcodeReturn,
  1421  					wasm.OpcodeEnd, wasm.OpcodeI32Const, 13, wasm.OpcodeReturn,
  1422  					wasm.OpcodeEnd, wasm.OpcodeI32Const, 14, wasm.OpcodeReturn,
  1423  					wasm.OpcodeEnd, wasm.OpcodeI32Const, 15, wasm.OpcodeReturn,
  1424  					wasm.OpcodeEnd, wasm.OpcodeI32Const, 16, wasm.OpcodeReturn,
  1425  					wasm.OpcodeEnd,
  1426  				}},
  1427  			},
  1428  		},
  1429  	}
  1430  
  1431  	BrTableWithArg = TestCase{
  1432  		Name: "br_table_with_arg",
  1433  		Module: &wasm.Module{
  1434  			TypeSection:     []wasm.FunctionType{i32i32_i32, v_i32},
  1435  			ExportSection:   []wasm.Export{{Name: ExportedFunctionName, Type: wasm.ExternTypeFunc, Index: 0}},
  1436  			FunctionSection: []wasm.Index{0},
  1437  			CodeSection: []wasm.Code{
  1438  				{Body: []byte{
  1439  					wasm.OpcodeBlock, 1, // Signature v_i32,
  1440  					wasm.OpcodeBlock, 1, // Signature v_i32,
  1441  					wasm.OpcodeBlock, 1, // Signature v_i32,
  1442  					wasm.OpcodeBlock, 1, // Signature v_i32,
  1443  					wasm.OpcodeBlock, 1, // Signature v_i32,
  1444  					wasm.OpcodeBlock, 1, // Signature v_i32,
  1445  					wasm.OpcodeLocalGet, 1, // Argument to each destination.
  1446  					wasm.OpcodeLocalGet, 0,
  1447  					wasm.OpcodeBrTable,
  1448  					6,                // size of label vector
  1449  					0, 1, 2, 3, 4, 5, // labels.
  1450  					0, // default label
  1451  					wasm.OpcodeEnd, wasm.OpcodeI32Const, 11, wasm.OpcodeI32Add, wasm.OpcodeReturn,
  1452  					wasm.OpcodeEnd, wasm.OpcodeI32Const, 12, wasm.OpcodeI32Add, wasm.OpcodeReturn,
  1453  					wasm.OpcodeEnd, wasm.OpcodeI32Const, 13, wasm.OpcodeI32Add, wasm.OpcodeReturn,
  1454  					wasm.OpcodeEnd, wasm.OpcodeI32Const, 14, wasm.OpcodeI32Add, wasm.OpcodeReturn,
  1455  					wasm.OpcodeEnd, wasm.OpcodeI32Const, 15, wasm.OpcodeI32Add, wasm.OpcodeReturn,
  1456  					wasm.OpcodeEnd, wasm.OpcodeI32Const, 16, wasm.OpcodeI32Add, wasm.OpcodeReturn,
  1457  					wasm.OpcodeUnreachable,
  1458  					wasm.OpcodeEnd,
  1459  				}},
  1460  			},
  1461  		},
  1462  	}
  1463  
  1464  	IfThenEndNestingUnreachableIfThenElseEnd = TestCase{
  1465  		// This has been detected by fuzzing. This should belong to internal/integration_test/fuzzcases eventually,
  1466  		// but for now, wazevo should have its own cases under engine/wazevo.
  1467  		Name: "if_then_end_nesting_unreachable_if_then_else_end",
  1468  		// (module
  1469  		//  (type (;0;) (func (param f64 f64 f64)))
  1470  		//  (func (;0;) (type 0) (param f64 f64 f64)
  1471  		//    block (result i64) ;; label = @1
  1472  		//      memory.size
  1473  		//      if ;; label = @2
  1474  		//        memory.size
  1475  		//        br 0 (;@2;)
  1476  		//        if ;; label = @3
  1477  		//        else
  1478  		//        end
  1479  		//        drop
  1480  		//      end
  1481  		//      i64.const 0
  1482  		//    end
  1483  		//    drop
  1484  		//  )
  1485  		//  (memory (;0;) 4554)
  1486  		//)
  1487  		Module: &wasm.Module{
  1488  			TypeSection: []wasm.FunctionType{
  1489  				{Params: []wasm.ValueType{f64, f64, f64}},
  1490  				{Results: []wasm.ValueType{i64}},
  1491  			},
  1492  
  1493  			ExportSection:   []wasm.Export{{Name: ExportedFunctionName, Type: wasm.ExternTypeFunc, Index: 0}},
  1494  			MemorySection:   &wasm.Memory{Min: 4554},
  1495  			FunctionSection: []wasm.Index{0},
  1496  			CodeSection: []wasm.Code{{Body: []byte{
  1497  				wasm.OpcodeBlock, 1, // Signature v_i64,
  1498  				wasm.OpcodeMemorySize, 0,
  1499  				wasm.OpcodeIf, blockSignature_vv,
  1500  				wasm.OpcodeMemorySize, 0,
  1501  				wasm.OpcodeBr, 0x0, // label=0
  1502  				wasm.OpcodeIf, blockSignature_vv,
  1503  				wasm.OpcodeElse,
  1504  				wasm.OpcodeEnd,
  1505  				wasm.OpcodeDrop,
  1506  				wasm.OpcodeEnd,
  1507  				wasm.OpcodeI64Const, 0,
  1508  				wasm.OpcodeEnd,
  1509  				wasm.OpcodeDrop,
  1510  				wasm.OpcodeEnd,
  1511  			}}},
  1512  		},
  1513  	}
  1514  
  1515  	VecBitSelect = TestCase{
  1516  		Name: "vector_bit_select",
  1517  		Module: &wasm.Module{
  1518  			TypeSection:     []wasm.FunctionType{{Params: []wasm.ValueType{v128, v128, v128}, Results: []wasm.ValueType{v128, v128}}},
  1519  			ExportSection:   []wasm.Export{{Name: ExportedFunctionName, Type: wasm.ExternTypeFunc, Index: 0}},
  1520  			FunctionSection: []wasm.Index{0},
  1521  			CodeSection: []wasm.Code{{Body: []byte{
  1522  				// In arm64, the "C" of BSL instruction is overwritten by the result,
  1523  				// so this case can be used to ensure that it is still alive if 'c' is used somewhere else,
  1524  				// which in this case is as a return value.
  1525  				wasm.OpcodeLocalGet, 0,
  1526  				wasm.OpcodeLocalGet, 1,
  1527  				wasm.OpcodeLocalGet, 2,
  1528  				wasm.OpcodeVecPrefix, wasm.OpcodeVecV128Bitselect,
  1529  				wasm.OpcodeLocalGet, 2, // Returns the 'c' as-is.
  1530  				wasm.OpcodeEnd,
  1531  			}}},
  1532  		},
  1533  	}
  1534  
  1535  	VecShuffle = TestCase{
  1536  		Name:   "shuffle",
  1537  		Module: VecShuffleWithLane(0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 30, 31),
  1538  	}
  1539  )
  1540  
  1541  // VecShuffleWithLane returns a VecShuffle test with a custom 16-bytes immediate (lane indexes).
  1542  func VecShuffleWithLane(lane ...byte) *wasm.Module {
  1543  	return &wasm.Module{
  1544  		TypeSection:     []wasm.FunctionType{{Params: []wasm.ValueType{v128, v128}, Results: []wasm.ValueType{v128}}},
  1545  		ExportSection:   []wasm.Export{{Name: ExportedFunctionName, Type: wasm.ExternTypeFunc, Index: 0}},
  1546  		FunctionSection: []wasm.Index{0},
  1547  		CodeSection: []wasm.Code{{
  1548  			Body: append(append([]byte{
  1549  				wasm.OpcodeLocalGet, 0,
  1550  				wasm.OpcodeLocalGet, 1,
  1551  				wasm.OpcodeVecPrefix, wasm.OpcodeVecV128i8x16Shuffle,
  1552  			}, lane...),
  1553  				wasm.OpcodeEnd),
  1554  		}},
  1555  	}
  1556  }
  1557  
  1558  type TestCase struct {
  1559  	Name             string
  1560  	Imported, Module *wasm.Module
  1561  }
  1562  
  1563  func SingleFunctionModule(typ wasm.FunctionType, body []byte, localTypes []wasm.ValueType) *wasm.Module {
  1564  	return &wasm.Module{
  1565  		TypeSection:     []wasm.FunctionType{typ},
  1566  		FunctionSection: []wasm.Index{0},
  1567  		CodeSection: []wasm.Code{{
  1568  			LocalTypes: localTypes,
  1569  			Body:       body,
  1570  		}},
  1571  		ExportSection: []wasm.Export{{Name: ExportedFunctionName, Type: wasm.ExternTypeFunc, Index: 0}},
  1572  	}
  1573  }
  1574  
  1575  var (
  1576  	vv                              = wasm.FunctionType{}
  1577  	v_i32                           = wasm.FunctionType{Results: []wasm.ValueType{i32}}
  1578  	v_i32i32                        = wasm.FunctionType{Results: []wasm.ValueType{i32, i32}}
  1579  	i32_v                           = wasm.FunctionType{Params: []wasm.ValueType{i32}}
  1580  	i32_i32                         = wasm.FunctionType{Params: []wasm.ValueType{i32}, Results: []wasm.ValueType{i32}}
  1581  	i32i32_i32                      = wasm.FunctionType{Params: []wasm.ValueType{i32, i32}, Results: []wasm.ValueType{i32}}
  1582  	i32i32_i32i32                   = wasm.FunctionType{Params: []wasm.ValueType{i32, i32}, Results: []wasm.ValueType{i32, i32}}
  1583  	i32i32i64i64f32f32f64f64_i32i64 = wasm.FunctionType{Params: []wasm.ValueType{i32, i32, i64, i64, f32, f32, f64, f64}, Results: []wasm.ValueType{i32, i64, f32, f64}}
  1584  	i32_i32i32                      = wasm.FunctionType{Params: []wasm.ValueType{i32}, Results: []wasm.ValueType{i32, i32}}
  1585  	i32f32f64_v                     = wasm.FunctionType{Params: []wasm.ValueType{i32, f32, f64}, Results: nil}
  1586  	i64f32f64_i64f32f64             = wasm.FunctionType{Params: []wasm.ValueType{i64, f32, f64}, Results: []wasm.ValueType{i64, f32, f64}}
  1587  )
  1588  
  1589  const (
  1590  	i32  = wasm.ValueTypeI32
  1591  	i64  = wasm.ValueTypeI64
  1592  	f32  = wasm.ValueTypeF32
  1593  	f64  = wasm.ValueTypeF64
  1594  	v128 = wasm.ValueTypeV128
  1595  
  1596  	blockSignature_vv = 0x40 // 0x40 is the v_v signature in 33-bit signed. See wasm.DecodeBlockType.
  1597  )
  1598  
  1599  func maskedBuf(size int) []byte {
  1600  	ret := make([]byte, size)
  1601  	for i := range ret {
  1602  		ret[i] = byte(i)
  1603  	}
  1604  	return ret
  1605  }
  1606  
  1607  func constExprI32(i int32) wasm.ConstantExpression {
  1608  	return wasm.ConstantExpression{
  1609  		Opcode: wasm.OpcodeI32Const,
  1610  		Data:   leb128.EncodeInt32(i),
  1611  	}
  1612  }
  1613  
  1614  func constExprI64(i int64) wasm.ConstantExpression {
  1615  	return wasm.ConstantExpression{
  1616  		Opcode: wasm.OpcodeI64Const,
  1617  		Data:   leb128.EncodeInt64(i),
  1618  	}
  1619  }
  1620  
  1621  func constExprF32(i float32) wasm.ConstantExpression {
  1622  	b := math.Float32bits(i)
  1623  	return wasm.ConstantExpression{
  1624  		Opcode: wasm.OpcodeF32Const,
  1625  		Data:   []byte{byte(b), byte(b >> 8), byte(b >> 16), byte(b >> 24)},
  1626  	}
  1627  }
  1628  
  1629  func constExprF64(i float64) wasm.ConstantExpression {
  1630  	b := math.Float64bits(i)
  1631  	return wasm.ConstantExpression{
  1632  		Opcode: wasm.OpcodeF64Const,
  1633  		Data: []byte{
  1634  			byte(b), byte(b >> 8), byte(b >> 16), byte(b >> 24),
  1635  			byte(b >> 32), byte(b >> 40), byte(b >> 48), byte(b >> 56),
  1636  		},
  1637  	}
  1638  }