github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/internal/engine/wazevo/testcases/testcases.go (about) 1 package testcases 2 3 import ( 4 "math" 5 6 "github.com/bananabytelabs/wazero/internal/leb128" 7 "github.com/bananabytelabs/wazero/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 }