github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/engine/wazevo/frontend/frontend_test.go (about) 1 package frontend 2 3 import ( 4 "testing" 5 6 "github.com/wasilibs/wazerox/api" 7 "github.com/wasilibs/wazerox/internal/engine/wazevo/ssa" 8 "github.com/wasilibs/wazerox/internal/engine/wazevo/testcases" 9 "github.com/wasilibs/wazerox/internal/engine/wazevo/wazevoapi" 10 "github.com/wasilibs/wazerox/internal/testing/require" 11 "github.com/wasilibs/wazerox/internal/wasm" 12 ) 13 14 func TestCompiler_LowerToSSA(t *testing.T) { 15 // Most of the logic should look similar to Cranelift's Wasm frontend, so when you want to see 16 // what output should look like, you can run: 17 // `~/wasmtime/target/debug/clif-util wasm --target aarch64-apple-darwin testcase.wat -p -t` 18 for _, tc := range []struct { 19 name string 20 ensureTermination bool 21 needListener bool 22 // m is the *wasm.Module to be compiled in this test. 23 m *wasm.Module 24 // targetIndex is the index of a local function to be compiled in this test. 25 targetIndex wasm.Index 26 // exp is the *unoptimized* expected SSA IR for the function m.FunctionSection[targetIndex]. 27 exp string 28 // expAfterOpt is not empty when we want to check the result after optimization passes. 29 expAfterOpt string 30 }{ 31 { 32 name: "empty", m: testcases.Empty.Module, 33 exp: ` 34 blk0: (exec_ctx:i64, module_ctx:i64) 35 Jump blk_ret 36 `, 37 }, 38 { 39 name: "unreachable", m: testcases.Unreachable.Module, 40 exp: ` 41 blk0: (exec_ctx:i64, module_ctx:i64) 42 Exit exec_ctx, unreachable 43 `, 44 }, 45 { 46 name: testcases.OnlyReturn.Name, m: testcases.OnlyReturn.Module, 47 exp: ` 48 blk0: (exec_ctx:i64, module_ctx:i64) 49 Return 50 `, 51 }, 52 { 53 name: "params", m: testcases.Params.Module, 54 exp: ` 55 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:f32, v4:f64) 56 Return 57 `, 58 }, 59 { 60 name: "add/sub params return", m: testcases.AddSubParamsReturn.Module, 61 exp: ` 62 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32) 63 v4:i32 = Iadd v2, v3 64 v5:i32 = Isub v4, v2 65 Jump blk_ret, v5 66 `, 67 }, 68 { 69 name: "add/sub params return / listener", m: testcases.AddSubParamsReturn.Module, 70 needListener: true, 71 exp: ` 72 signatures: 73 sig1: i64i32i32i32_v 74 sig2: i64i32i32_v 75 76 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32) 77 Store module_ctx, exec_ctx, 0x8 78 v4:i64 = Load module_ctx, 0x8 79 v5:i64 = Load v4, 0x0 80 v6:i32 = Iconst_32 0x0 81 CallIndirect v5:sig1, exec_ctx, v6, v2, v3 82 v7:i32 = Iadd v2, v3 83 v8:i32 = Isub v7, v2 84 Store module_ctx, exec_ctx, 0x8 85 v9:i64 = Load module_ctx, 0x10 86 v10:i64 = Load v9, 0x0 87 v11:i32 = Iconst_32 0x0 88 CallIndirect v10:sig2, exec_ctx, v11, v8 89 Jump blk_ret, v8 90 `, 91 }, 92 { 93 name: "locals", m: testcases.Locals.Module, 94 exp: ` 95 blk0: (exec_ctx:i64, module_ctx:i64) 96 v2:i32 = Iconst_32 0x0 97 v3:i64 = Iconst_64 0x0 98 v4:f32 = F32const 0.000000 99 v5:f64 = F64const 0.000000 100 Jump blk_ret 101 `, 102 expAfterOpt: ` 103 blk0: (exec_ctx:i64, module_ctx:i64) 104 Jump blk_ret 105 `, 106 }, 107 { 108 name: "selects", m: testcases.Selects.Module, 109 exp: ` 110 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32, v4:i64, v5:i64, v6:f32, v7:f32, v8:f64, v9:f64) 111 v10:i32 = Icmp eq, v4, v5 112 v11:i32 = Select v10, v2, v3 113 v12:i64 = Select v3, v4, v5 114 v13:i32 = Fcmp gt, v8, v9 115 v14:f32 = Select v13, v6, v7 116 v15:i32 = Fcmp neq, v6, v7 117 v16:f64 = Select v15, v8, v9 118 Jump blk_ret, v11, v12, v14, v16 119 `, 120 }, 121 { 122 name: "local param tee return", m: testcases.LocalParamTeeReturn.Module, 123 exp: ` 124 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 125 v3:i32 = Iconst_32 0x0 126 Jump blk_ret, v2, v2 127 `, 128 expAfterOpt: ` 129 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 130 Jump blk_ret, v2, v2 131 `, 132 }, 133 { 134 name: "locals + params", m: testcases.LocalsParams.Module, 135 exp: ` 136 blk0: (exec_ctx:i64, module_ctx:i64, v2:i64, v3:f32, v4:f64) 137 v5:i32 = Iconst_32 0x0 138 v6:i64 = Iconst_64 0x0 139 v7:f32 = F32const 0.000000 140 v8:f64 = F64const 0.000000 141 v9:i64 = Iadd v2, v2 142 v10:i64 = Isub v9, v2 143 v11:f32 = Fadd v3, v3 144 v12:f32 = Fsub v11, v3 145 v13:f32 = Fmul v12, v3 146 v14:f32 = Fdiv v13, v3 147 v15:f32 = Fmax v14, v3 148 v16:f32 = Fmin v15, v3 149 v17:f64 = Fadd v4, v4 150 v18:f64 = Fsub v17, v4 151 v19:f64 = Fmul v18, v4 152 v20:f64 = Fdiv v19, v4 153 v21:f64 = Fmax v20, v4 154 v22:f64 = Fmin v21, v4 155 Jump blk_ret, v10, v16, v22 156 `, 157 expAfterOpt: ` 158 blk0: (exec_ctx:i64, module_ctx:i64, v2:i64, v3:f32, v4:f64) 159 v9:i64 = Iadd v2, v2 160 v10:i64 = Isub v9, v2 161 v11:f32 = Fadd v3, v3 162 v12:f32 = Fsub v11, v3 163 v13:f32 = Fmul v12, v3 164 v14:f32 = Fdiv v13, v3 165 v15:f32 = Fmax v14, v3 166 v16:f32 = Fmin v15, v3 167 v17:f64 = Fadd v4, v4 168 v18:f64 = Fsub v17, v4 169 v19:f64 = Fmul v18, v4 170 v20:f64 = Fdiv v19, v4 171 v21:f64 = Fmax v20, v4 172 v22:f64 = Fmin v21, v4 173 Jump blk_ret, v10, v16, v22 174 `, 175 }, 176 { 177 name: "locals + params + return", m: testcases.LocalParamReturn.Module, 178 exp: ` 179 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 180 v3:i32 = Iconst_32 0x0 181 Jump blk_ret, v2, v3 182 `, 183 }, 184 { 185 name: "swap param and return", m: testcases.SwapParamAndReturn.Module, 186 exp: ` 187 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32) 188 Jump blk_ret, v3, v2 189 `, 190 }, 191 { 192 name: "swap params and return", m: testcases.SwapParamsAndReturn.Module, 193 exp: ` 194 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32) 195 Jump blk1 196 197 blk1: () <-- (blk0) 198 Jump blk_ret, v3, v2 199 `, 200 }, 201 { 202 name: "block - br", m: testcases.BlockBr.Module, 203 exp: ` 204 blk0: (exec_ctx:i64, module_ctx:i64) 205 v2:i32 = Iconst_32 0x0 206 v3:i64 = Iconst_64 0x0 207 v4:f32 = F32const 0.000000 208 v5:f64 = F64const 0.000000 209 Jump blk1 210 211 blk1: () <-- (blk0) 212 Jump blk_ret 213 `, 214 }, 215 { 216 name: "block - br_if", m: testcases.BlockBrIf.Module, 217 exp: ` 218 blk0: (exec_ctx:i64, module_ctx:i64) 219 v2:i32 = Iconst_32 0x0 220 Brnz v2, blk1 221 Jump blk2 222 223 blk1: () <-- (blk0) 224 Jump blk_ret 225 226 blk2: () <-- (blk0) 227 Exit exec_ctx, unreachable 228 `, 229 }, 230 { 231 name: "loop - br", m: testcases.LoopBr.Module, 232 exp: ` 233 blk0: (exec_ctx:i64, module_ctx:i64) 234 Jump blk1 235 236 blk1: () <-- (blk0,blk1) 237 Jump blk1 238 239 blk2: () 240 `, 241 expAfterOpt: ` 242 blk0: (exec_ctx:i64, module_ctx:i64) 243 Jump blk1 244 245 blk1: () <-- (blk0,blk1) 246 Jump blk1 247 `, 248 }, 249 { 250 name: "loop - br / ensure termination", m: testcases.LoopBr.Module, 251 ensureTermination: true, 252 exp: ` 253 signatures: 254 sig2: i64_v 255 256 blk0: (exec_ctx:i64, module_ctx:i64) 257 Jump blk1 258 259 blk1: () <-- (blk0,blk1) 260 v2:i64 = Load exec_ctx, 0x58 261 CallIndirect v2:sig2, exec_ctx 262 Jump blk1 263 264 blk2: () 265 `, 266 expAfterOpt: ` 267 signatures: 268 sig2: i64_v 269 270 blk0: (exec_ctx:i64, module_ctx:i64) 271 Jump blk1 272 273 blk1: () <-- (blk0,blk1) 274 v2:i64 = Load exec_ctx, 0x58 275 CallIndirect v2:sig2, exec_ctx 276 Jump blk1 277 `, 278 }, 279 { 280 name: "loop - br_if", m: testcases.LoopBrIf.Module, 281 exp: ` 282 blk0: (exec_ctx:i64, module_ctx:i64) 283 Jump blk1 284 285 blk1: () <-- (blk0,blk1) 286 v2:i32 = Iconst_32 0x1 287 Brnz v2, blk1 288 Jump blk3 289 290 blk2: () 291 292 blk3: () <-- (blk1) 293 Return 294 `, 295 expAfterOpt: ` 296 blk0: (exec_ctx:i64, module_ctx:i64) 297 Jump blk1 298 299 blk1: () <-- (blk0,blk1) 300 v2:i32 = Iconst_32 0x1 301 Brnz v2, blk1 302 Jump blk3 303 304 blk3: () <-- (blk1) 305 Return 306 `, 307 }, 308 { 309 name: "block - block - br", m: testcases.BlockBlockBr.Module, 310 exp: ` 311 blk0: (exec_ctx:i64, module_ctx:i64) 312 v2:i32 = Iconst_32 0x0 313 v3:i64 = Iconst_64 0x0 314 v4:f32 = F32const 0.000000 315 v5:f64 = F64const 0.000000 316 Jump blk1 317 318 blk1: () <-- (blk0) 319 Jump blk_ret 320 321 blk2: () 322 `, 323 expAfterOpt: ` 324 blk0: (exec_ctx:i64, module_ctx:i64) 325 Jump blk1 326 327 blk1: () <-- (blk0) 328 Jump blk_ret 329 `, 330 }, 331 { 332 name: "if without else", m: testcases.IfWithoutElse.Module, 333 exp: ` 334 blk0: (exec_ctx:i64, module_ctx:i64) 335 v2:i32 = Iconst_32 0x0 336 Brz v2, blk2 337 Jump blk1 338 339 blk1: () <-- (blk0) 340 Jump blk3 341 342 blk2: () <-- (blk0) 343 Jump blk3 344 345 blk3: () <-- (blk1,blk2) 346 Jump blk_ret 347 `, 348 }, 349 { 350 name: "if-else", m: testcases.IfElse.Module, 351 exp: ` 352 blk0: (exec_ctx:i64, module_ctx:i64) 353 v2:i32 = Iconst_32 0x0 354 Brz v2, blk2 355 Jump blk1 356 357 blk1: () <-- (blk0) 358 Jump blk3 359 360 blk2: () <-- (blk0) 361 Jump blk_ret 362 363 blk3: () <-- (blk1) 364 Jump blk_ret 365 `, 366 }, 367 { 368 name: "single predecessor local refs", m: testcases.SinglePredecessorLocalRefs.Module, 369 exp: ` 370 blk0: (exec_ctx:i64, module_ctx:i64) 371 v2:i32 = Iconst_32 0x0 372 v3:i32 = Iconst_32 0x0 373 v4:i32 = Iconst_32 0x0 374 Brz v2, blk2 375 Jump blk1 376 377 blk1: () <-- (blk0) 378 Return v4 379 380 blk2: () <-- (blk0) 381 Jump blk3 382 383 blk3: () <-- (blk2) 384 Jump blk_ret, v2 385 `, 386 expAfterOpt: ` 387 blk0: (exec_ctx:i64, module_ctx:i64) 388 v2:i32 = Iconst_32 0x0 389 v4:i32 = Iconst_32 0x0 390 Brz v2, blk2 391 Jump blk1 392 393 blk1: () <-- (blk0) 394 Return v4 395 396 blk2: () <-- (blk0) 397 Jump blk3 398 399 blk3: () <-- (blk2) 400 Jump blk_ret, v2 401 `, 402 }, 403 { 404 name: "multi predecessors local ref", 405 m: testcases.MultiPredecessorLocalRef.Module, 406 exp: ` 407 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32) 408 v4:i32 = Iconst_32 0x0 409 Brz v2, blk2 410 Jump blk1 411 412 blk1: () <-- (blk0) 413 Jump blk3, v2 414 415 blk2: () <-- (blk0) 416 Jump blk3, v3 417 418 blk3: (v5:i32) <-- (blk1,blk2) 419 Jump blk_ret, v5 420 `, 421 expAfterOpt: ` 422 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32) 423 Brz v2, blk2 424 Jump blk1 425 426 blk1: () <-- (blk0) 427 Jump blk3, v2 428 429 blk2: () <-- (blk0) 430 Jump blk3, v3 431 432 blk3: (v5:i32) <-- (blk1,blk2) 433 Jump blk_ret, v5 434 `, 435 }, 436 { 437 name: "reference value from unsealed block", 438 m: testcases.ReferenceValueFromUnsealedBlock.Module, 439 exp: ` 440 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 441 v3:i32 = Iconst_32 0x0 442 Jump blk1, v2 443 444 blk1: (v4:i32) <-- (blk0) 445 Return v4 446 447 blk2: () 448 `, 449 expAfterOpt: ` 450 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 451 Jump blk1 452 453 blk1: () <-- (blk0) 454 Return v2 455 `, 456 }, 457 { 458 name: "reference value from unsealed block - #2", 459 m: testcases.ReferenceValueFromUnsealedBlock2.Module, 460 exp: ` 461 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 462 Jump blk1, v2 463 464 blk1: (v3:i32) <-- (blk0,blk1) 465 Brnz v3, blk1, v3 466 Jump blk4 467 468 blk2: () <-- (blk3) 469 v4:i32 = Iconst_32 0x0 470 Jump blk_ret, v4 471 472 blk3: () <-- (blk4) 473 Jump blk2 474 475 blk4: () <-- (blk1) 476 Jump blk3 477 `, 478 expAfterOpt: ` 479 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 480 Jump blk1 481 482 blk1: () <-- (blk0,blk1) 483 Brnz v2, blk1 484 Jump blk4 485 486 blk2: () <-- (blk3) 487 v4:i32 = Iconst_32 0x0 488 Jump blk_ret, v4 489 490 blk3: () <-- (blk4) 491 Jump blk2 492 493 blk4: () <-- (blk1) 494 Jump blk3 495 `, 496 }, 497 { 498 name: "reference value from unsealed block - #3", 499 m: testcases.ReferenceValueFromUnsealedBlock3.Module, 500 exp: ` 501 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 502 Jump blk1, v2 503 504 blk1: (v3:i32) <-- (blk0,blk3) 505 Brnz v3, blk_ret 506 Jump blk4 507 508 blk2: () 509 510 blk3: () <-- (blk4) 511 v4:i32 = Iconst_32 0x1 512 Jump blk1, v4 513 514 blk4: () <-- (blk1) 515 Jump blk3 516 `, 517 expAfterOpt: ` 518 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 519 Jump blk1, v2 520 521 blk1: (v3:i32) <-- (blk0,blk3) 522 Brnz v3, blk_ret 523 Jump blk4 524 525 blk3: () <-- (blk4) 526 v4:i32 = Iconst_32 0x1 527 Jump blk1, v4 528 529 blk4: () <-- (blk1) 530 Jump blk3 531 `, 532 }, 533 { 534 name: "call", 535 m: testcases.Call.Module, 536 exp: ` 537 signatures: 538 sig1: i64i64_i32 539 sig2: i64i64i32i32_i32 540 sig3: i64i64i32_i32i32 541 542 blk0: (exec_ctx:i64, module_ctx:i64) 543 Store module_ctx, exec_ctx, 0x8 544 v2:i32 = Call f1:sig1, exec_ctx, module_ctx 545 v3:i32 = Iconst_32 0x5 546 Store module_ctx, exec_ctx, 0x8 547 v4:i32 = Call f2:sig2, exec_ctx, module_ctx, v2, v3 548 Store module_ctx, exec_ctx, 0x8 549 v5:i32, v6:i32 = Call f3:sig3, exec_ctx, module_ctx, v4 550 Jump blk_ret, v5, v6 551 `, 552 }, 553 { 554 name: "call_many_params", 555 m: testcases.CallManyParams.Module, 556 exp: ` 557 signatures: 558 sig1: i64i64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64_v 559 560 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i64, v4:f32, v5:f64) 561 Store module_ctx, exec_ctx, 0x8 562 Call f1:sig1, exec_ctx, module_ctx, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5 563 Jump blk_ret 564 `, 565 }, 566 { 567 name: "call_many_returns", 568 m: testcases.CallManyReturns.Module, 569 exp: ` 570 signatures: 571 sig0: i64i64i32i64f32f64_i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64 572 573 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i64, v4:f32, v5:f64) 574 Store module_ctx, exec_ctx, 0x8 575 v6:i32, v7:i64, v8:f32, v9:f64, v10:i32, v11:i64, v12:f32, v13:f64, v14:i32, v15:i64, v16:f32, v17:f64, v18:i32, v19:i64, v20:f32, v21:f64, v22:i32, v23:i64, v24:f32, v25:f64, v26:i32, v27:i64, v28:f32, v29:f64, v30:i32, v31:i64, v32:f32, v33:f64, v34:i32, v35:i64, v36:f32, v37:f64, v38:i32, v39:i64, v40:f32, v41:f64, v42:i32, v43:i64, v44:f32, v45:f64 = Call f1:sig0, exec_ctx, module_ctx, v2, v3, v4, v5 576 Jump blk_ret, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45 577 `, 578 }, 579 { 580 name: "integer comparisons", m: testcases.IntegerComparisons.Module, 581 exp: ` 582 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32, v4:i64, v5:i64) 583 v6:i32 = Icmp eq, v2, v3 584 v7:i32 = Icmp eq, v4, v5 585 v8:i32 = Icmp neq, v2, v3 586 v9:i32 = Icmp neq, v4, v5 587 v10:i32 = Icmp lt_s, v2, v3 588 v11:i32 = Icmp lt_s, v4, v5 589 v12:i32 = Icmp lt_u, v2, v3 590 v13:i32 = Icmp lt_u, v4, v5 591 v14:i32 = Icmp gt_s, v2, v3 592 v15:i32 = Icmp gt_s, v4, v5 593 v16:i32 = Icmp gt_u, v2, v3 594 v17:i32 = Icmp gt_u, v4, v5 595 v18:i32 = Icmp le_s, v2, v3 596 v19:i32 = Icmp le_s, v4, v5 597 v20:i32 = Icmp le_u, v2, v3 598 v21:i32 = Icmp le_u, v4, v5 599 v22:i32 = Icmp ge_s, v2, v3 600 v23:i32 = Icmp ge_s, v4, v5 601 v24:i32 = Icmp ge_u, v2, v3 602 v25:i32 = Icmp ge_u, v4, v5 603 Jump blk_ret, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25 604 `, 605 expAfterOpt: ` 606 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32, v4:i64, v5:i64) 607 v6:i32 = Icmp eq, v2, v3 608 v7:i32 = Icmp eq, v4, v5 609 v8:i32 = Icmp neq, v2, v3 610 v9:i32 = Icmp neq, v4, v5 611 v10:i32 = Icmp lt_s, v2, v3 612 v11:i32 = Icmp lt_s, v4, v5 613 v12:i32 = Icmp lt_u, v2, v3 614 v13:i32 = Icmp lt_u, v4, v5 615 v14:i32 = Icmp gt_s, v2, v3 616 v15:i32 = Icmp gt_s, v4, v5 617 v16:i32 = Icmp gt_u, v2, v3 618 v17:i32 = Icmp gt_u, v4, v5 619 v18:i32 = Icmp le_s, v2, v3 620 v19:i32 = Icmp le_s, v4, v5 621 v20:i32 = Icmp le_u, v2, v3 622 v21:i32 = Icmp le_u, v4, v5 623 v22:i32 = Icmp ge_s, v2, v3 624 v23:i32 = Icmp ge_s, v4, v5 625 v24:i32 = Icmp ge_u, v2, v3 626 v25:i32 = Icmp ge_u, v4, v5 627 Jump blk_ret, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25 628 `, 629 }, 630 { 631 name: "integer bitwise", m: testcases.IntegerBitwise.Module, 632 exp: ` 633 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32, v4:i64, v5:i64) 634 v6:i32 = Band v2, v3 635 v7:i32 = Bor v2, v3 636 v8:i32 = Bxor v2, v3 637 v9:i32 = Rotr v2, v3 638 v10:i64 = Band v4, v5 639 v11:i64 = Bor v4, v5 640 v12:i64 = Bxor v4, v5 641 v13:i64 = Iconst_64 0x8 642 v14:i64 = Ishl v5, v13 643 v15:i64 = Bxor v4, v14 644 v16:i64 = Rotl v4, v5 645 v17:i64 = Rotr v4, v5 646 Jump blk_ret, v6, v7, v8, v9, v10, v11, v12, v15, v16, v17 647 `, 648 }, 649 { 650 name: "integer shift", m: testcases.IntegerShift.Module, 651 exp: ` 652 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32, v4:i64, v5:i64) 653 v6:i32 = Ishl v2, v3 654 v7:i32 = Iconst_32 0x1f 655 v8:i32 = Ishl v2, v7 656 v9:i64 = Ishl v4, v5 657 v10:i64 = Iconst_64 0x20 658 v11:i64 = Ishl v4, v10 659 v12:i32 = Ushr v2, v3 660 v13:i32 = Iconst_32 0x1f 661 v14:i32 = Ushr v2, v13 662 v15:i64 = Ushr v4, v5 663 v16:i64 = Iconst_64 0x20 664 v17:i64 = Ushr v4, v16 665 v18:i32 = Sshr v2, v3 666 v19:i32 = Iconst_32 0x1f 667 v20:i32 = Sshr v2, v19 668 v21:i64 = Sshr v4, v5 669 v22:i64 = Iconst_64 0x20 670 v23:i64 = Sshr v4, v22 671 Jump blk_ret, v6, v8, v9, v11, v12, v14, v15, v17, v18, v20, v21, v23 672 `, 673 }, 674 { 675 name: "integer extension", m: testcases.IntegerExtensions.Module, 676 exp: ` 677 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i64) 678 v4:i64 = SExtend v2, 32->64 679 v5:i64 = UExtend v2, 32->64 680 v6:i64 = SExtend v3, 8->64 681 v7:i64 = SExtend v3, 16->64 682 v8:i64 = SExtend v3, 32->64 683 v9:i32 = SExtend v2, 8->32 684 v10:i32 = SExtend v2, 16->32 685 Jump blk_ret, v4, v5, v6, v7, v8, v9, v10 686 `, 687 }, 688 { 689 name: "integer bit counts", m: testcases.IntegerBitCounts.Module, 690 exp: ` 691 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i64) 692 v4:i32 = Clz v2 693 v5:i32 = Ctz v2 694 v6:i32 = Popcnt v2 695 v7:i64 = Clz v3 696 v8:i64 = Ctz v3 697 v9:i64 = Popcnt v3 698 Jump blk_ret, v4, v5, v6, v7, v8, v9 699 `, 700 }, 701 { 702 name: "float comparisons", m: testcases.FloatComparisons.Module, 703 exp: ` 704 blk0: (exec_ctx:i64, module_ctx:i64, v2:f32, v3:f32, v4:f64, v5:f64) 705 v6:i32 = Fcmp eq, v2, v3 706 v7:i32 = Fcmp neq, v2, v3 707 v8:i32 = Fcmp lt, v2, v3 708 v9:i32 = Fcmp gt, v2, v3 709 v10:i32 = Fcmp le, v2, v3 710 v11:i32 = Fcmp ge, v2, v3 711 v12:i32 = Fcmp eq, v4, v5 712 v13:i32 = Fcmp neq, v4, v5 713 v14:i32 = Fcmp lt, v4, v5 714 v15:i32 = Fcmp gt, v4, v5 715 v16:i32 = Fcmp le, v4, v5 716 v17:i32 = Fcmp ge, v4, v5 717 Jump blk_ret, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17 718 `, 719 }, 720 { 721 name: "float conversions", m: testcases.FloatConversions.Module, 722 exp: ` 723 blk0: (exec_ctx:i64, module_ctx:i64, v2:f64, v3:f32) 724 v4:i64 = FcvtToSint v2 725 v5:i64 = FcvtToSint v3 726 v6:i32 = FcvtToSint v2 727 v7:i32 = FcvtToSint v3 728 v8:i64 = FcvtToUint v2 729 v9:i64 = FcvtToUint v3 730 v10:i32 = FcvtToUint v2 731 v11:i32 = FcvtToUint v3 732 v12:f32 = Fdemote v2 733 v13:f64 = Fpromote v3 734 Jump blk_ret, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13 735 `, 736 }, 737 { 738 name: "non-trapping float conversions", m: testcases.NonTrappingFloatConversions.Module, 739 exp: ` 740 blk0: (exec_ctx:i64, module_ctx:i64, v2:f64, v3:f32) 741 v4:i64 = FcvtToSintSat v2 742 v5:i64 = FcvtToSintSat v3 743 v6:i32 = FcvtToSintSat v2 744 v7:i32 = FcvtToSintSat v3 745 v8:i64 = FcvtToUintSat v2 746 v9:i64 = FcvtToUintSat v3 747 v10:i32 = FcvtToUintSat v2 748 v11:i32 = FcvtToUintSat v3 749 Jump blk_ret, v4, v5, v6, v7, v8, v9, v10, v11 750 `, 751 }, 752 { 753 name: "loop with param and results", m: testcases.LoopBrWithParamResults.Module, 754 exp: ` 755 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32) 756 Jump blk1, v2, v3 757 758 blk1: (v4:i32,v5:i32) <-- (blk0,blk1) 759 v7:i32 = Iconst_32 0x1 760 Brnz v7, blk1, v4, v5 761 Jump blk3 762 763 blk2: (v6:i32) <-- (blk3) 764 Jump blk_ret, v6 765 766 blk3: () <-- (blk1) 767 Jump blk2, v4 768 `, 769 expAfterOpt: ` 770 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32) 771 Jump blk1 772 773 blk1: () <-- (blk0,blk1) 774 v7:i32 = Iconst_32 0x1 775 Brnz v7, blk1 776 Jump blk3 777 778 blk2: () <-- (blk3) 779 Jump blk_ret, v2 780 781 blk3: () <-- (blk1) 782 Jump blk2 783 `, 784 }, 785 { 786 name: "many_params_small_results", 787 m: testcases.ManyParamsSmallResults.Module, 788 targetIndex: 0, 789 exp: ` 790 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i64, v4:f32, v5:f64, v6:i32, v7:i64, v8:f32, v9:f64, v10:i32, v11:i64, v12:f32, v13:f64, v14:i32, v15:i64, v16:f32, v17:f64, v18:i32, v19:i64, v20:f32, v21:f64, v22:i32, v23:i64, v24:f32, v25:f64, v26:i32, v27:i64, v28:f32, v29:f64, v30:i32, v31:i64, v32:f32, v33:f64, v34:i32, v35:i64, v36:f32, v37:f64, v38:i32, v39:i64, v40:f32, v41:f64) 791 Jump blk_ret, v2, v11, v20, v29 792 `, 793 expAfterOpt: ` 794 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i64, v4:f32, v5:f64, v6:i32, v7:i64, v8:f32, v9:f64, v10:i32, v11:i64, v12:f32, v13:f64, v14:i32, v15:i64, v16:f32, v17:f64, v18:i32, v19:i64, v20:f32, v21:f64, v22:i32, v23:i64, v24:f32, v25:f64, v26:i32, v27:i64, v28:f32, v29:f64, v30:i32, v31:i64, v32:f32, v33:f64, v34:i32, v35:i64, v36:f32, v37:f64, v38:i32, v39:i64, v40:f32, v41:f64) 795 Jump blk_ret, v2, v11, v20, v29 796 `, 797 }, 798 { 799 name: "small_params_many_results", 800 m: testcases.SmallParamsManyResults.Module, 801 targetIndex: 0, 802 exp: ` 803 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i64, v4:f32, v5:f64) 804 Jump blk_ret, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5 805 `, 806 expAfterOpt: ` 807 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i64, v4:f32, v5:f64) 808 Jump blk_ret, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5 809 `, 810 }, 811 { 812 name: "many_params_many_results", 813 m: testcases.ManyParamsManyResults.Module, 814 targetIndex: 0, 815 exp: ` 816 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i64, v4:f32, v5:f64, v6:i32, v7:i64, v8:f32, v9:f64, v10:i32, v11:i64, v12:f32, v13:f64, v14:i32, v15:i64, v16:f32, v17:f64, v18:i32, v19:i64, v20:f32, v21:f64, v22:i32, v23:i64, v24:f32, v25:f64, v26:i32, v27:i64, v28:f32, v29:f64, v30:i32, v31:i64, v32:f32, v33:f64, v34:i32, v35:i64, v36:f32, v37:f64, v38:i32, v39:i64, v40:f32, v41:f64) 817 Jump blk_ret, v41, v40, v39, v38, v37, v36, v35, v34, v33, v32, v31, v30, v29, v28, v27, v26, v25, v24, v23, v22, v21, v20, v19, v18, v17, v16, v15, v14, v13, v12, v11, v10, v9, v8, v7, v6, v5, v4, v3, v2 818 `, 819 expAfterOpt: ` 820 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i64, v4:f32, v5:f64, v6:i32, v7:i64, v8:f32, v9:f64, v10:i32, v11:i64, v12:f32, v13:f64, v14:i32, v15:i64, v16:f32, v17:f64, v18:i32, v19:i64, v20:f32, v21:f64, v22:i32, v23:i64, v24:f32, v25:f64, v26:i32, v27:i64, v28:f32, v29:f64, v30:i32, v31:i64, v32:f32, v33:f64, v34:i32, v35:i64, v36:f32, v37:f64, v38:i32, v39:i64, v40:f32, v41:f64) 821 Jump blk_ret, v41, v40, v39, v38, v37, v36, v35, v34, v33, v32, v31, v30, v29, v28, v27, v26, v25, v24, v23, v22, v21, v20, v19, v18, v17, v16, v15, v14, v13, v12, v11, v10, v9, v8, v7, v6, v5, v4, v3, v2 822 `, 823 }, 824 { 825 name: "many_middle_values", 826 m: testcases.ManyMiddleValues.Module, 827 exp: ` 828 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:f32) 829 v4:i32 = Iconst_32 0x1 830 v5:i32 = Imul v2, v4 831 v6:i32 = Iconst_32 0x2 832 v7:i32 = Imul v2, v6 833 v8:i32 = Iconst_32 0x3 834 v9:i32 = Imul v2, v8 835 v10:i32 = Iconst_32 0x4 836 v11:i32 = Imul v2, v10 837 v12:i32 = Iconst_32 0x5 838 v13:i32 = Imul v2, v12 839 v14:i32 = Iconst_32 0x6 840 v15:i32 = Imul v2, v14 841 v16:i32 = Iconst_32 0x7 842 v17:i32 = Imul v2, v16 843 v18:i32 = Iconst_32 0x8 844 v19:i32 = Imul v2, v18 845 v20:i32 = Iconst_32 0x9 846 v21:i32 = Imul v2, v20 847 v22:i32 = Iconst_32 0xa 848 v23:i32 = Imul v2, v22 849 v24:i32 = Iconst_32 0xb 850 v25:i32 = Imul v2, v24 851 v26:i32 = Iconst_32 0xc 852 v27:i32 = Imul v2, v26 853 v28:i32 = Iconst_32 0xd 854 v29:i32 = Imul v2, v28 855 v30:i32 = Iconst_32 0xe 856 v31:i32 = Imul v2, v30 857 v32:i32 = Iconst_32 0xf 858 v33:i32 = Imul v2, v32 859 v34:i32 = Iconst_32 0x10 860 v35:i32 = Imul v2, v34 861 v36:i32 = Iconst_32 0x11 862 v37:i32 = Imul v2, v36 863 v38:i32 = Iconst_32 0x12 864 v39:i32 = Imul v2, v38 865 v40:i32 = Iconst_32 0x13 866 v41:i32 = Imul v2, v40 867 v42:i32 = Iconst_32 0x14 868 v43:i32 = Imul v2, v42 869 v44:i32 = Iadd v41, v43 870 v45:i32 = Iadd v39, v44 871 v46:i32 = Iadd v37, v45 872 v47:i32 = Iadd v35, v46 873 v48:i32 = Iadd v33, v47 874 v49:i32 = Iadd v31, v48 875 v50:i32 = Iadd v29, v49 876 v51:i32 = Iadd v27, v50 877 v52:i32 = Iadd v25, v51 878 v53:i32 = Iadd v23, v52 879 v54:i32 = Iadd v21, v53 880 v55:i32 = Iadd v19, v54 881 v56:i32 = Iadd v17, v55 882 v57:i32 = Iadd v15, v56 883 v58:i32 = Iadd v13, v57 884 v59:i32 = Iadd v11, v58 885 v60:i32 = Iadd v9, v59 886 v61:i32 = Iadd v7, v60 887 v62:i32 = Iadd v5, v61 888 v63:f32 = F32const 1.000000 889 v64:f32 = Fmul v3, v63 890 v65:f32 = F32const 2.000000 891 v66:f32 = Fmul v3, v65 892 v67:f32 = F32const 3.000000 893 v68:f32 = Fmul v3, v67 894 v69:f32 = F32const 4.000000 895 v70:f32 = Fmul v3, v69 896 v71:f32 = F32const 5.000000 897 v72:f32 = Fmul v3, v71 898 v73:f32 = F32const 6.000000 899 v74:f32 = Fmul v3, v73 900 v75:f32 = F32const 7.000000 901 v76:f32 = Fmul v3, v75 902 v77:f32 = F32const 8.000000 903 v78:f32 = Fmul v3, v77 904 v79:f32 = F32const 9.000000 905 v80:f32 = Fmul v3, v79 906 v81:f32 = F32const 10.000000 907 v82:f32 = Fmul v3, v81 908 v83:f32 = F32const 11.000000 909 v84:f32 = Fmul v3, v83 910 v85:f32 = F32const 12.000000 911 v86:f32 = Fmul v3, v85 912 v87:f32 = F32const 13.000000 913 v88:f32 = Fmul v3, v87 914 v89:f32 = F32const 14.000000 915 v90:f32 = Fmul v3, v89 916 v91:f32 = F32const 15.000000 917 v92:f32 = Fmul v3, v91 918 v93:f32 = F32const 16.000000 919 v94:f32 = Fmul v3, v93 920 v95:f32 = F32const 17.000000 921 v96:f32 = Fmul v3, v95 922 v97:f32 = F32const 18.000000 923 v98:f32 = Fmul v3, v97 924 v99:f32 = F32const 19.000000 925 v100:f32 = Fmul v3, v99 926 v101:f32 = F32const 20.000000 927 v102:f32 = Fmul v3, v101 928 v103:f32 = Fadd v100, v102 929 v104:f32 = Fadd v98, v103 930 v105:f32 = Fadd v96, v104 931 v106:f32 = Fadd v94, v105 932 v107:f32 = Fadd v92, v106 933 v108:f32 = Fadd v90, v107 934 v109:f32 = Fadd v88, v108 935 v110:f32 = Fadd v86, v109 936 v111:f32 = Fadd v84, v110 937 v112:f32 = Fadd v82, v111 938 v113:f32 = Fadd v80, v112 939 v114:f32 = Fadd v78, v113 940 v115:f32 = Fadd v76, v114 941 v116:f32 = Fadd v74, v115 942 v117:f32 = Fadd v72, v116 943 v118:f32 = Fadd v70, v117 944 v119:f32 = Fadd v68, v118 945 v120:f32 = Fadd v66, v119 946 v121:f32 = Fadd v64, v120 947 Jump blk_ret, v62, v121 948 `, 949 }, 950 { 951 name: "recursive_fibonacci", m: testcases.FibonacciRecursive.Module, 952 exp: ` 953 signatures: 954 sig0: i64i64i32_i32 955 956 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 957 v3:i32 = Iconst_32 0x2 958 v4:i32 = Icmp lt_s, v2, v3 959 Brz v4, blk2 960 Jump blk1 961 962 blk1: () <-- (blk0) 963 Return v2 964 965 blk2: () <-- (blk0) 966 Jump blk3 967 968 blk3: () <-- (blk2) 969 v5:i32 = Iconst_32 0x1 970 v6:i32 = Isub v2, v5 971 Store module_ctx, exec_ctx, 0x8 972 v7:i32 = Call f0:sig0, exec_ctx, module_ctx, v6 973 v8:i32 = Iconst_32 0x2 974 v9:i32 = Isub v2, v8 975 Store module_ctx, exec_ctx, 0x8 976 v10:i32 = Call f0:sig0, exec_ctx, module_ctx, v9 977 v11:i32 = Iadd v7, v10 978 Jump blk_ret, v11 979 `, 980 expAfterOpt: ` 981 signatures: 982 sig0: i64i64i32_i32 983 984 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 985 v3:i32 = Iconst_32 0x2 986 v4:i32 = Icmp lt_s, v2, v3 987 Brz v4, blk2 988 Jump blk1 989 990 blk1: () <-- (blk0) 991 Return v2 992 993 blk2: () <-- (blk0) 994 Jump blk3 995 996 blk3: () <-- (blk2) 997 v5:i32 = Iconst_32 0x1 998 v6:i32 = Isub v2, v5 999 Store module_ctx, exec_ctx, 0x8 1000 v7:i32 = Call f0:sig0, exec_ctx, module_ctx, v6 1001 v8:i32 = Iconst_32 0x2 1002 v9:i32 = Isub v2, v8 1003 Store module_ctx, exec_ctx, 0x8 1004 v10:i32 = Call f0:sig0, exec_ctx, module_ctx, v9 1005 v11:i32 = Iadd v7, v10 1006 Jump blk_ret, v11 1007 `, 1008 }, 1009 { 1010 name: "memory_store_basic", m: testcases.MemoryStoreBasic.Module, 1011 exp: ` 1012 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32) 1013 v4:i64 = Iconst_64 0x4 1014 v5:i64 = UExtend v2, 32->64 1015 v6:i64 = Uload32 module_ctx, 0x10 1016 v7:i64 = Iadd v5, v4 1017 v8:i32 = Icmp lt_u, v6, v7 1018 ExitIfTrue v8, exec_ctx, memory_out_of_bounds 1019 v9:i64 = Load module_ctx, 0x8 1020 v10:i64 = Iadd v9, v5 1021 Store v3, v10, 0x0 1022 v11:i64 = Iconst_64 0x4 1023 v12:i64 = UExtend v2, 32->64 1024 v13:i64 = Iadd v12, v11 1025 v14:i32 = Icmp lt_u, v6, v13 1026 ExitIfTrue v14, exec_ctx, memory_out_of_bounds 1027 v15:i64 = Iadd v9, v12 1028 v16:i32 = Load v15, 0x0 1029 Jump blk_ret, v16 1030 `, 1031 }, 1032 { 1033 name: "memory_load_basic", m: testcases.MemoryLoadBasic.Module, 1034 exp: ` 1035 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 1036 v3:i64 = Iconst_64 0x4 1037 v4:i64 = UExtend v2, 32->64 1038 v5:i64 = Uload32 module_ctx, 0x10 1039 v6:i64 = Iadd v4, v3 1040 v7:i32 = Icmp lt_u, v5, v6 1041 ExitIfTrue v7, exec_ctx, memory_out_of_bounds 1042 v8:i64 = Load module_ctx, 0x8 1043 v9:i64 = Iadd v8, v4 1044 v10:i32 = Load v9, 0x0 1045 Jump blk_ret, v10 1046 `, 1047 }, 1048 { 1049 name: "memory_load_basic2", m: testcases.MemoryLoadBasic2.Module, 1050 exp: ` 1051 signatures: 1052 sig1: i64i64_v 1053 1054 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 1055 v3:i32 = Iconst_32 0x0 1056 v4:i32 = Icmp eq, v2, v3 1057 Brz v4, blk2 1058 Jump blk1 1059 1060 blk1: () <-- (blk0) 1061 Store module_ctx, exec_ctx, 0x8 1062 Call f1:sig1, exec_ctx, module_ctx 1063 v5:i64 = Load module_ctx, 0x8 1064 v6:i64 = Uload32 module_ctx, 0x10 1065 Jump blk3, v2 1066 1067 blk2: () <-- (blk0) 1068 Jump blk3, v2 1069 1070 blk3: (v7:i32) <-- (blk1,blk2) 1071 v8:i64 = Iconst_64 0x4 1072 v9:i64 = UExtend v7, 32->64 1073 v10:i64 = Uload32 module_ctx, 0x10 1074 v11:i64 = Iadd v9, v8 1075 v12:i32 = Icmp lt_u, v10, v11 1076 ExitIfTrue v12, exec_ctx, memory_out_of_bounds 1077 v13:i64 = Load module_ctx, 0x8 1078 v14:i64 = Iadd v13, v9 1079 v15:i32 = Load v14, 0x0 1080 Jump blk_ret, v15 1081 `, 1082 expAfterOpt: ` 1083 signatures: 1084 sig1: i64i64_v 1085 1086 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 1087 v3:i32 = Iconst_32 0x0 1088 v4:i32 = Icmp eq, v2, v3 1089 Brz v4, blk2 1090 Jump blk1 1091 1092 blk1: () <-- (blk0) 1093 Store module_ctx, exec_ctx, 0x8 1094 Call f1:sig1, exec_ctx, module_ctx 1095 Jump blk3 1096 1097 blk2: () <-- (blk0) 1098 Jump blk3 1099 1100 blk3: () <-- (blk1,blk2) 1101 v8:i64 = Iconst_64 0x4 1102 v9:i64 = UExtend v2, 32->64 1103 v10:i64 = Uload32 module_ctx, 0x10 1104 v11:i64 = Iadd v9, v8 1105 v12:i32 = Icmp lt_u, v10, v11 1106 ExitIfTrue v12, exec_ctx, memory_out_of_bounds 1107 v13:i64 = Load module_ctx, 0x8 1108 v14:i64 = Iadd v13, v9 1109 v15:i32 = Load v14, 0x0 1110 Jump blk_ret, v15 1111 `, 1112 }, 1113 { 1114 name: "imported_function_call", m: testcases.ImportedFunctionCall.Module, 1115 exp: ` 1116 signatures: 1117 sig1: i64i64i32i32_i32 1118 1119 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 1120 Store module_ctx, exec_ctx, 0x8 1121 v3:i64 = Load module_ctx, 0x8 1122 v4:i64 = Load module_ctx, 0x10 1123 v5:i32 = CallIndirect v3:sig1, exec_ctx, v4, v2, v2 1124 Jump blk_ret, v5 1125 `, 1126 }, 1127 { 1128 name: "memory_loads", m: testcases.MemoryLoads.Module, 1129 exp: ` 1130 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 1131 v3:i64 = Iconst_64 0x4 1132 v4:i64 = UExtend v2, 32->64 1133 v5:i64 = Uload32 module_ctx, 0x10 1134 v6:i64 = Iadd v4, v3 1135 v7:i32 = Icmp lt_u, v5, v6 1136 ExitIfTrue v7, exec_ctx, memory_out_of_bounds 1137 v8:i64 = Load module_ctx, 0x8 1138 v9:i64 = Iadd v8, v4 1139 v10:i32 = Load v9, 0x0 1140 v11:i64 = Iconst_64 0x8 1141 v12:i64 = UExtend v2, 32->64 1142 v13:i64 = Iadd v12, v11 1143 v14:i32 = Icmp lt_u, v5, v13 1144 ExitIfTrue v14, exec_ctx, memory_out_of_bounds 1145 v15:i64 = Iadd v8, v12 1146 v16:i64 = Load v15, 0x0 1147 v17:i64 = Iconst_64 0x4 1148 v18:i64 = UExtend v2, 32->64 1149 v19:i64 = Iadd v18, v17 1150 v20:i32 = Icmp lt_u, v5, v19 1151 ExitIfTrue v20, exec_ctx, memory_out_of_bounds 1152 v21:i64 = Iadd v8, v18 1153 v22:f32 = Load v21, 0x0 1154 v23:i64 = Iconst_64 0x8 1155 v24:i64 = UExtend v2, 32->64 1156 v25:i64 = Iadd v24, v23 1157 v26:i32 = Icmp lt_u, v5, v25 1158 ExitIfTrue v26, exec_ctx, memory_out_of_bounds 1159 v27:i64 = Iadd v8, v24 1160 v28:f64 = Load v27, 0x0 1161 v29:i64 = Iconst_64 0x13 1162 v30:i64 = UExtend v2, 32->64 1163 v31:i64 = Iadd v30, v29 1164 v32:i32 = Icmp lt_u, v5, v31 1165 ExitIfTrue v32, exec_ctx, memory_out_of_bounds 1166 v33:i64 = Iadd v8, v30 1167 v34:i32 = Load v33, 0xf 1168 v35:i64 = Iconst_64 0x17 1169 v36:i64 = UExtend v2, 32->64 1170 v37:i64 = Iadd v36, v35 1171 v38:i32 = Icmp lt_u, v5, v37 1172 ExitIfTrue v38, exec_ctx, memory_out_of_bounds 1173 v39:i64 = Iadd v8, v36 1174 v40:i64 = Load v39, 0xf 1175 v41:i64 = Iconst_64 0x13 1176 v42:i64 = UExtend v2, 32->64 1177 v43:i64 = Iadd v42, v41 1178 v44:i32 = Icmp lt_u, v5, v43 1179 ExitIfTrue v44, exec_ctx, memory_out_of_bounds 1180 v45:i64 = Iadd v8, v42 1181 v46:f32 = Load v45, 0xf 1182 v47:i64 = Iconst_64 0x17 1183 v48:i64 = UExtend v2, 32->64 1184 v49:i64 = Iadd v48, v47 1185 v50:i32 = Icmp lt_u, v5, v49 1186 ExitIfTrue v50, exec_ctx, memory_out_of_bounds 1187 v51:i64 = Iadd v8, v48 1188 v52:f64 = Load v51, 0xf 1189 v53:i64 = Iconst_64 0x1 1190 v54:i64 = UExtend v2, 32->64 1191 v55:i64 = Iadd v54, v53 1192 v56:i32 = Icmp lt_u, v5, v55 1193 ExitIfTrue v56, exec_ctx, memory_out_of_bounds 1194 v57:i64 = Iadd v8, v54 1195 v58:i32 = Sload8 v57, 0x0 1196 v59:i64 = Iconst_64 0x10 1197 v60:i64 = UExtend v2, 32->64 1198 v61:i64 = Iadd v60, v59 1199 v62:i32 = Icmp lt_u, v5, v61 1200 ExitIfTrue v62, exec_ctx, memory_out_of_bounds 1201 v63:i64 = Iadd v8, v60 1202 v64:i32 = Sload8 v63, 0xf 1203 v65:i64 = Iconst_64 0x1 1204 v66:i64 = UExtend v2, 32->64 1205 v67:i64 = Iadd v66, v65 1206 v68:i32 = Icmp lt_u, v5, v67 1207 ExitIfTrue v68, exec_ctx, memory_out_of_bounds 1208 v69:i64 = Iadd v8, v66 1209 v70:i32 = Uload8 v69, 0x0 1210 v71:i64 = Iconst_64 0x10 1211 v72:i64 = UExtend v2, 32->64 1212 v73:i64 = Iadd v72, v71 1213 v74:i32 = Icmp lt_u, v5, v73 1214 ExitIfTrue v74, exec_ctx, memory_out_of_bounds 1215 v75:i64 = Iadd v8, v72 1216 v76:i32 = Uload8 v75, 0xf 1217 v77:i64 = Iconst_64 0x2 1218 v78:i64 = UExtend v2, 32->64 1219 v79:i64 = Iadd v78, v77 1220 v80:i32 = Icmp lt_u, v5, v79 1221 ExitIfTrue v80, exec_ctx, memory_out_of_bounds 1222 v81:i64 = Iadd v8, v78 1223 v82:i32 = Sload16 v81, 0x0 1224 v83:i64 = Iconst_64 0x11 1225 v84:i64 = UExtend v2, 32->64 1226 v85:i64 = Iadd v84, v83 1227 v86:i32 = Icmp lt_u, v5, v85 1228 ExitIfTrue v86, exec_ctx, memory_out_of_bounds 1229 v87:i64 = Iadd v8, v84 1230 v88:i32 = Sload16 v87, 0xf 1231 v89:i64 = Iconst_64 0x2 1232 v90:i64 = UExtend v2, 32->64 1233 v91:i64 = Iadd v90, v89 1234 v92:i32 = Icmp lt_u, v5, v91 1235 ExitIfTrue v92, exec_ctx, memory_out_of_bounds 1236 v93:i64 = Iadd v8, v90 1237 v94:i32 = Uload16 v93, 0x0 1238 v95:i64 = Iconst_64 0x11 1239 v96:i64 = UExtend v2, 32->64 1240 v97:i64 = Iadd v96, v95 1241 v98:i32 = Icmp lt_u, v5, v97 1242 ExitIfTrue v98, exec_ctx, memory_out_of_bounds 1243 v99:i64 = Iadd v8, v96 1244 v100:i32 = Uload16 v99, 0xf 1245 v101:i64 = Iconst_64 0x1 1246 v102:i64 = UExtend v2, 32->64 1247 v103:i64 = Iadd v102, v101 1248 v104:i32 = Icmp lt_u, v5, v103 1249 ExitIfTrue v104, exec_ctx, memory_out_of_bounds 1250 v105:i64 = Iadd v8, v102 1251 v106:i64 = Sload8 v105, 0x0 1252 v107:i64 = Iconst_64 0x10 1253 v108:i64 = UExtend v2, 32->64 1254 v109:i64 = Iadd v108, v107 1255 v110:i32 = Icmp lt_u, v5, v109 1256 ExitIfTrue v110, exec_ctx, memory_out_of_bounds 1257 v111:i64 = Iadd v8, v108 1258 v112:i64 = Sload8 v111, 0xf 1259 v113:i64 = Iconst_64 0x1 1260 v114:i64 = UExtend v2, 32->64 1261 v115:i64 = Iadd v114, v113 1262 v116:i32 = Icmp lt_u, v5, v115 1263 ExitIfTrue v116, exec_ctx, memory_out_of_bounds 1264 v117:i64 = Iadd v8, v114 1265 v118:i64 = Uload8 v117, 0x0 1266 v119:i64 = Iconst_64 0x10 1267 v120:i64 = UExtend v2, 32->64 1268 v121:i64 = Iadd v120, v119 1269 v122:i32 = Icmp lt_u, v5, v121 1270 ExitIfTrue v122, exec_ctx, memory_out_of_bounds 1271 v123:i64 = Iadd v8, v120 1272 v124:i64 = Uload8 v123, 0xf 1273 v125:i64 = Iconst_64 0x2 1274 v126:i64 = UExtend v2, 32->64 1275 v127:i64 = Iadd v126, v125 1276 v128:i32 = Icmp lt_u, v5, v127 1277 ExitIfTrue v128, exec_ctx, memory_out_of_bounds 1278 v129:i64 = Iadd v8, v126 1279 v130:i64 = Sload16 v129, 0x0 1280 v131:i64 = Iconst_64 0x11 1281 v132:i64 = UExtend v2, 32->64 1282 v133:i64 = Iadd v132, v131 1283 v134:i32 = Icmp lt_u, v5, v133 1284 ExitIfTrue v134, exec_ctx, memory_out_of_bounds 1285 v135:i64 = Iadd v8, v132 1286 v136:i64 = Sload16 v135, 0xf 1287 v137:i64 = Iconst_64 0x2 1288 v138:i64 = UExtend v2, 32->64 1289 v139:i64 = Iadd v138, v137 1290 v140:i32 = Icmp lt_u, v5, v139 1291 ExitIfTrue v140, exec_ctx, memory_out_of_bounds 1292 v141:i64 = Iadd v8, v138 1293 v142:i64 = Uload16 v141, 0x0 1294 v143:i64 = Iconst_64 0x11 1295 v144:i64 = UExtend v2, 32->64 1296 v145:i64 = Iadd v144, v143 1297 v146:i32 = Icmp lt_u, v5, v145 1298 ExitIfTrue v146, exec_ctx, memory_out_of_bounds 1299 v147:i64 = Iadd v8, v144 1300 v148:i64 = Uload16 v147, 0xf 1301 v149:i64 = Iconst_64 0x4 1302 v150:i64 = UExtend v2, 32->64 1303 v151:i64 = Iadd v150, v149 1304 v152:i32 = Icmp lt_u, v5, v151 1305 ExitIfTrue v152, exec_ctx, memory_out_of_bounds 1306 v153:i64 = Iadd v8, v150 1307 v154:i64 = Sload32 v153, 0x0 1308 v155:i64 = Iconst_64 0x13 1309 v156:i64 = UExtend v2, 32->64 1310 v157:i64 = Iadd v156, v155 1311 v158:i32 = Icmp lt_u, v5, v157 1312 ExitIfTrue v158, exec_ctx, memory_out_of_bounds 1313 v159:i64 = Iadd v8, v156 1314 v160:i64 = Sload32 v159, 0xf 1315 v161:i64 = Iconst_64 0x4 1316 v162:i64 = UExtend v2, 32->64 1317 v163:i64 = Iadd v162, v161 1318 v164:i32 = Icmp lt_u, v5, v163 1319 ExitIfTrue v164, exec_ctx, memory_out_of_bounds 1320 v165:i64 = Iadd v8, v162 1321 v166:i64 = Uload32 v165, 0x0 1322 v167:i64 = Iconst_64 0x13 1323 v168:i64 = UExtend v2, 32->64 1324 v169:i64 = Iadd v168, v167 1325 v170:i32 = Icmp lt_u, v5, v169 1326 ExitIfTrue v170, exec_ctx, memory_out_of_bounds 1327 v171:i64 = Iadd v8, v168 1328 v172:i64 = Uload32 v171, 0xf 1329 Jump blk_ret, v10, v16, v22, v28, v34, v40, v46, v52, v58, v64, v70, v76, v82, v88, v94, v100, v106, v112, v118, v124, v130, v136, v142, v148, v154, v160, v166, v172 1330 `, 1331 }, 1332 { 1333 name: "globals_get", 1334 m: testcases.GlobalsGet.Module, 1335 exp: ` 1336 blk0: (exec_ctx:i64, module_ctx:i64) 1337 v2:i64 = Load module_ctx, 0x8 1338 v3:i32 = Load v2, 0x8 1339 v4:i64 = Load module_ctx, 0x10 1340 v5:i64 = Load v4, 0x8 1341 v6:i64 = Load module_ctx, 0x18 1342 v7:f32 = Load v6, 0x8 1343 v8:i64 = Load module_ctx, 0x20 1344 v9:f64 = Load v8, 0x8 1345 Jump blk_ret, v3, v5, v7, v9 1346 `, 1347 }, 1348 { 1349 name: "globals_set", 1350 m: testcases.GlobalsSet.Module, 1351 exp: ` 1352 blk0: (exec_ctx:i64, module_ctx:i64) 1353 v2:i32 = Iconst_32 0x1 1354 v3:i64 = Load module_ctx, 0x8 1355 Store v2, v3, 0x8 1356 v4:i64 = Iconst_64 0x2 1357 v5:i64 = Load module_ctx, 0x10 1358 Store v4, v5, 0x8 1359 v6:f32 = F32const 3.000000 1360 v7:i64 = Load module_ctx, 0x18 1361 Store v6, v7, 0x8 1362 v8:f64 = F64const 4.000000 1363 v9:i64 = Load module_ctx, 0x20 1364 Store v8, v9, 0x8 1365 Jump blk_ret, v2, v4, v6, v8 1366 `, 1367 }, 1368 { 1369 name: "globals_mutable", 1370 m: testcases.GlobalsMutable.Module, 1371 exp: ` 1372 signatures: 1373 sig1: i64i64_v 1374 1375 blk0: (exec_ctx:i64, module_ctx:i64) 1376 v2:i64 = Load module_ctx, 0x8 1377 v3:i32 = Load v2, 0x8 1378 v4:i64 = Load module_ctx, 0x10 1379 v5:i64 = Load v4, 0x8 1380 v6:i64 = Load module_ctx, 0x18 1381 v7:f32 = Load v6, 0x8 1382 v8:i64 = Load module_ctx, 0x20 1383 v9:f64 = Load v8, 0x8 1384 Store module_ctx, exec_ctx, 0x8 1385 Call f1:sig1, exec_ctx, module_ctx 1386 v10:i64 = Load module_ctx, 0x8 1387 v11:i32 = Load v10, 0x8 1388 v12:i64 = Load module_ctx, 0x10 1389 v13:i64 = Load v12, 0x8 1390 v14:i64 = Load module_ctx, 0x18 1391 v15:f32 = Load v14, 0x8 1392 v16:i64 = Load module_ctx, 0x20 1393 v17:f64 = Load v16, 0x8 1394 Jump blk_ret, v3, v5, v7, v9, v11, v13, v15, v17 1395 `, 1396 expAfterOpt: ` 1397 signatures: 1398 sig1: i64i64_v 1399 1400 blk0: (exec_ctx:i64, module_ctx:i64) 1401 v2:i64 = Load module_ctx, 0x8 1402 v3:i32 = Load v2, 0x8 1403 v4:i64 = Load module_ctx, 0x10 1404 v5:i64 = Load v4, 0x8 1405 v6:i64 = Load module_ctx, 0x18 1406 v7:f32 = Load v6, 0x8 1407 v8:i64 = Load module_ctx, 0x20 1408 v9:f64 = Load v8, 0x8 1409 Store module_ctx, exec_ctx, 0x8 1410 Call f1:sig1, exec_ctx, module_ctx 1411 v10:i64 = Load module_ctx, 0x8 1412 v11:i32 = Load v10, 0x8 1413 v12:i64 = Load module_ctx, 0x10 1414 v13:i64 = Load v12, 0x8 1415 v14:i64 = Load module_ctx, 0x18 1416 v15:f32 = Load v14, 0x8 1417 v16:i64 = Load module_ctx, 0x20 1418 v17:f64 = Load v16, 0x8 1419 Jump blk_ret, v3, v5, v7, v9, v11, v13, v15, v17 1420 `, 1421 }, 1422 { 1423 name: "imported_memory_grow", 1424 m: testcases.ImportedMemoryGrow.Module, 1425 exp: ` 1426 signatures: 1427 sig0: i64i64_i32 1428 sig2: i64i32_i32 1429 1430 blk0: (exec_ctx:i64, module_ctx:i64) 1431 Store module_ctx, exec_ctx, 0x8 1432 v2:i64 = Load module_ctx, 0x18 1433 v3:i64 = Load module_ctx, 0x20 1434 v4:i32 = CallIndirect v2:sig0, exec_ctx, v3 1435 v5:i64 = Load module_ctx, 0x8 1436 v6:i64 = Load v5, 0x0 1437 v7:i64 = Load module_ctx, 0x8 1438 v8:i64 = Load v7, 0x8 1439 v9:i64 = Load module_ctx, 0x8 1440 v10:i32 = Load v9, 0x8 1441 v11:i32 = Iconst_32 0x10 1442 v12:i32 = Ushr v10, v11 1443 v13:i32 = Iconst_32 0xa 1444 Store module_ctx, exec_ctx, 0x8 1445 v14:i64 = Load exec_ctx, 0x48 1446 v15:i32 = CallIndirect v14:sig2, exec_ctx, v13 1447 v16:i64 = Load module_ctx, 0x8 1448 v17:i64 = Load v16, 0x0 1449 v18:i64 = Load module_ctx, 0x8 1450 v19:i64 = Load v18, 0x8 1451 Store module_ctx, exec_ctx, 0x8 1452 v20:i64 = Load module_ctx, 0x18 1453 v21:i64 = Load module_ctx, 0x20 1454 v22:i32 = CallIndirect v20:sig0, exec_ctx, v21 1455 v23:i64 = Load module_ctx, 0x8 1456 v24:i64 = Load v23, 0x0 1457 v25:i64 = Load module_ctx, 0x8 1458 v26:i64 = Load v25, 0x8 1459 v27:i64 = Load module_ctx, 0x8 1460 v28:i32 = Load v27, 0x8 1461 v29:i32 = Iconst_32 0x10 1462 v30:i32 = Ushr v28, v29 1463 Jump blk_ret, v4, v12, v22, v30 1464 `, 1465 expAfterOpt: ` 1466 signatures: 1467 sig0: i64i64_i32 1468 sig2: i64i32_i32 1469 1470 blk0: (exec_ctx:i64, module_ctx:i64) 1471 Store module_ctx, exec_ctx, 0x8 1472 v2:i64 = Load module_ctx, 0x18 1473 v3:i64 = Load module_ctx, 0x20 1474 v4:i32 = CallIndirect v2:sig0, exec_ctx, v3 1475 v9:i64 = Load module_ctx, 0x8 1476 v10:i32 = Load v9, 0x8 1477 v11:i32 = Iconst_32 0x10 1478 v12:i32 = Ushr v10, v11 1479 v13:i32 = Iconst_32 0xa 1480 Store module_ctx, exec_ctx, 0x8 1481 v14:i64 = Load exec_ctx, 0x48 1482 v15:i32 = CallIndirect v14:sig2, exec_ctx, v13 1483 Store module_ctx, exec_ctx, 0x8 1484 v20:i64 = Load module_ctx, 0x18 1485 v21:i64 = Load module_ctx, 0x20 1486 v22:i32 = CallIndirect v20:sig0, exec_ctx, v21 1487 v27:i64 = Load module_ctx, 0x8 1488 v28:i32 = Load v27, 0x8 1489 v29:i32 = Iconst_32 0x10 1490 v30:i32 = Ushr v28, v29 1491 Jump blk_ret, v4, v12, v22, v30 1492 `, 1493 }, 1494 { 1495 name: "memory_size_grow", 1496 m: testcases.MemorySizeGrow.Module, 1497 exp: ` 1498 signatures: 1499 sig1: i64i32_i32 1500 1501 blk0: (exec_ctx:i64, module_ctx:i64) 1502 v2:i32 = Iconst_32 0x1 1503 Store module_ctx, exec_ctx, 0x8 1504 v3:i64 = Load exec_ctx, 0x48 1505 v4:i32 = CallIndirect v3:sig1, exec_ctx, v2 1506 v5:i64 = Load module_ctx, 0x8 1507 v6:i64 = Uload32 module_ctx, 0x10 1508 v7:i32 = Load module_ctx, 0x10 1509 v8:i32 = Iconst_32 0x10 1510 v9:i32 = Ushr v7, v8 1511 v10:i32 = Iconst_32 0x1 1512 Store module_ctx, exec_ctx, 0x8 1513 v11:i64 = Load exec_ctx, 0x48 1514 v12:i32 = CallIndirect v11:sig1, exec_ctx, v10 1515 v13:i64 = Load module_ctx, 0x8 1516 v14:i64 = Uload32 module_ctx, 0x10 1517 Jump blk_ret, v4, v9, v12 1518 `, 1519 expAfterOpt: ` 1520 signatures: 1521 sig1: i64i32_i32 1522 1523 blk0: (exec_ctx:i64, module_ctx:i64) 1524 v2:i32 = Iconst_32 0x1 1525 Store module_ctx, exec_ctx, 0x8 1526 v3:i64 = Load exec_ctx, 0x48 1527 v4:i32 = CallIndirect v3:sig1, exec_ctx, v2 1528 v7:i32 = Load module_ctx, 0x10 1529 v8:i32 = Iconst_32 0x10 1530 v9:i32 = Ushr v7, v8 1531 v10:i32 = Iconst_32 0x1 1532 Store module_ctx, exec_ctx, 0x8 1533 v11:i64 = Load exec_ctx, 0x48 1534 v12:i32 = CallIndirect v11:sig1, exec_ctx, v10 1535 Jump blk_ret, v4, v9, v12 1536 `, 1537 }, 1538 { 1539 name: "call_indirect", m: testcases.CallIndirect.Module, 1540 exp: ` 1541 signatures: 1542 sig2: i64i64_i32 1543 1544 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 1545 v3:i64 = Load module_ctx, 0x10 1546 v4:i32 = Load v3, 0x8 1547 v5:i32 = Icmp ge_u, v2, v4 1548 ExitIfTrue v5, exec_ctx, table_out_of_bounds 1549 v6:i64 = Load v3, 0x0 1550 v7:i64 = Iconst_64 0x3 1551 v8:i32 = Ishl v2, v7 1552 v9:i64 = Iadd v6, v8 1553 v10:i64 = Load v9, 0x0 1554 v11:i64 = Iconst_64 0x0 1555 v12:i32 = Icmp eq, v10, v11 1556 ExitIfTrue v12, exec_ctx, indirect_call_null_pointer 1557 v13:i32 = Load v10, 0x10 1558 v14:i64 = Load module_ctx, 0x8 1559 v15:i32 = Load v14, 0x8 1560 v16:i32 = Icmp neq, v13, v15 1561 ExitIfTrue v16, exec_ctx, indirect_call_type_mismatch 1562 v17:i64 = Load v10, 0x0 1563 v18:i64 = Load v10, 0x8 1564 Store module_ctx, exec_ctx, 0x8 1565 v19:i32 = CallIndirect v17:sig2, exec_ctx, v18 1566 Jump blk_ret, v19 1567 `, 1568 }, 1569 { 1570 name: "br_table", m: testcases.BrTable.Module, 1571 exp: ` 1572 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 1573 BrTable v2, [blk7, blk8, blk9, blk10, blk11, blk12, blk13] 1574 1575 blk1: () <-- (blk12) 1576 v8:i32 = Iconst_32 0x10 1577 Return v8 1578 1579 blk2: () <-- (blk11) 1580 v7:i32 = Iconst_32 0xf 1581 Return v7 1582 1583 blk3: () <-- (blk10) 1584 v6:i32 = Iconst_32 0xe 1585 Return v6 1586 1587 blk4: () <-- (blk9) 1588 v5:i32 = Iconst_32 0xd 1589 Return v5 1590 1591 blk5: () <-- (blk8) 1592 v4:i32 = Iconst_32 0xc 1593 Return v4 1594 1595 blk6: () <-- (blk7,blk13) 1596 v3:i32 = Iconst_32 0xb 1597 Return v3 1598 1599 blk7: () <-- (blk0) 1600 Jump blk6 1601 1602 blk8: () <-- (blk0) 1603 Jump blk5 1604 1605 blk9: () <-- (blk0) 1606 Jump blk4 1607 1608 blk10: () <-- (blk0) 1609 Jump blk3 1610 1611 blk11: () <-- (blk0) 1612 Jump blk2 1613 1614 blk12: () <-- (blk0) 1615 Jump blk1 1616 1617 blk13: () <-- (blk0) 1618 Jump blk6 1619 `, 1620 }, 1621 { 1622 name: "br_table_with_arg", m: testcases.BrTableWithArg.Module, 1623 exp: ` 1624 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32) 1625 BrTable v2, [blk7, blk8, blk9, blk10, blk11, blk12, blk13] 1626 1627 blk1: (v4:i32) <-- (blk12) 1628 v20:i32 = Iconst_32 0x10 1629 v21:i32 = Iadd v4, v20 1630 Return v21 1631 1632 blk2: (v5:i32) <-- (blk11) 1633 v18:i32 = Iconst_32 0xf 1634 v19:i32 = Iadd v5, v18 1635 Return v19 1636 1637 blk3: (v6:i32) <-- (blk10) 1638 v16:i32 = Iconst_32 0xe 1639 v17:i32 = Iadd v6, v16 1640 Return v17 1641 1642 blk4: (v7:i32) <-- (blk9) 1643 v14:i32 = Iconst_32 0xd 1644 v15:i32 = Iadd v7, v14 1645 Return v15 1646 1647 blk5: (v8:i32) <-- (blk8) 1648 v12:i32 = Iconst_32 0xc 1649 v13:i32 = Iadd v8, v12 1650 Return v13 1651 1652 blk6: (v9:i32) <-- (blk7,blk13) 1653 v10:i32 = Iconst_32 0xb 1654 v11:i32 = Iadd v9, v10 1655 Return v11 1656 1657 blk7: () <-- (blk0) 1658 Jump blk6, v3 1659 1660 blk8: () <-- (blk0) 1661 Jump blk5, v3 1662 1663 blk9: () <-- (blk0) 1664 Jump blk4, v3 1665 1666 blk10: () <-- (blk0) 1667 Jump blk3, v3 1668 1669 blk11: () <-- (blk0) 1670 Jump blk2, v3 1671 1672 blk12: () <-- (blk0) 1673 Jump blk1, v3 1674 1675 blk13: () <-- (blk0) 1676 Jump blk6, v3 1677 `, 1678 1679 // TODO: these trivial two hop jumps should be optimized away. 1680 expAfterOpt: ` 1681 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32) 1682 BrTable v2, [blk7, blk8, blk9, blk10, blk11, blk12, blk13] 1683 1684 blk1: () <-- (blk12) 1685 v20:i32 = Iconst_32 0x10 1686 v21:i32 = Iadd v3, v20 1687 Return v21 1688 1689 blk2: () <-- (blk11) 1690 v18:i32 = Iconst_32 0xf 1691 v19:i32 = Iadd v3, v18 1692 Return v19 1693 1694 blk3: () <-- (blk10) 1695 v16:i32 = Iconst_32 0xe 1696 v17:i32 = Iadd v3, v16 1697 Return v17 1698 1699 blk4: () <-- (blk9) 1700 v14:i32 = Iconst_32 0xd 1701 v15:i32 = Iadd v3, v14 1702 Return v15 1703 1704 blk5: () <-- (blk8) 1705 v12:i32 = Iconst_32 0xc 1706 v13:i32 = Iadd v3, v12 1707 Return v13 1708 1709 blk6: () <-- (blk7,blk13) 1710 v10:i32 = Iconst_32 0xb 1711 v11:i32 = Iadd v3, v10 1712 Return v11 1713 1714 blk7: () <-- (blk0) 1715 Jump blk6 1716 1717 blk8: () <-- (blk0) 1718 Jump blk5 1719 1720 blk9: () <-- (blk0) 1721 Jump blk4 1722 1723 blk10: () <-- (blk0) 1724 Jump blk3 1725 1726 blk11: () <-- (blk0) 1727 Jump blk2 1728 1729 blk12: () <-- (blk0) 1730 Jump blk1 1731 1732 blk13: () <-- (blk0) 1733 Jump blk6 1734 `, 1735 }, 1736 { 1737 name: "if_then_end_nesting_unreachable_if_then_else_end", m: testcases.IfThenEndNestingUnreachableIfThenElseEnd.Module, 1738 exp: ` 1739 blk0: (exec_ctx:i64, module_ctx:i64, v2:f64, v3:f64, v4:f64) 1740 v6:i32 = Load module_ctx, 0x10 1741 v7:i32 = Iconst_32 0x10 1742 v8:i32 = Ushr v6, v7 1743 Brz v8, blk3 1744 Jump blk2 1745 1746 blk1: (v5:i64) <-- (blk4) 1747 Jump blk_ret 1748 1749 blk2: () <-- (blk0) 1750 v9:i32 = Load module_ctx, 0x10 1751 v10:i32 = Iconst_32 0x10 1752 v11:i32 = Ushr v9, v10 1753 Jump blk4 1754 1755 blk3: () <-- (blk0) 1756 Jump blk4 1757 1758 blk4: () <-- (blk2,blk3) 1759 v12:i64 = Iconst_64 0x0 1760 Jump blk1, v12 1761 `, 1762 expAfterOpt: ` 1763 blk0: (exec_ctx:i64, module_ctx:i64, v2:f64, v3:f64, v4:f64) 1764 v6:i32 = Load module_ctx, 0x10 1765 v7:i32 = Iconst_32 0x10 1766 v8:i32 = Ushr v6, v7 1767 Brz v8, blk3 1768 Jump blk2 1769 1770 blk1: () <-- (blk4) 1771 Jump blk_ret 1772 1773 blk2: () <-- (blk0) 1774 Jump blk4 1775 1776 blk3: () <-- (blk0) 1777 Jump blk4 1778 1779 blk4: () <-- (blk2,blk3) 1780 Jump blk1 1781 `, 1782 }, 1783 { 1784 name: "VecShuffle", 1785 m: testcases.VecShuffle.Module, 1786 exp: ` 1787 blk0: (exec_ctx:i64, module_ctx:i64, v2:v128, v3:v128) 1788 v4:v128 = Shuffle.[0 1 2 3 4 5 6 7 24 25 26 27 28 29 30 31] v2, v3 1789 Jump blk_ret, v4 1790 `, 1791 }, 1792 } { 1793 1794 tc := tc 1795 t.Run(tc.name, func(t *testing.T) { 1796 // Just in case let's check the test module is valid. 1797 err := tc.m.Validate(api.CoreFeaturesV2) 1798 require.NoError(t, err, "invalid test case module!") 1799 1800 b := ssa.NewBuilder() 1801 1802 offset := wazevoapi.NewModuleContextOffsetData(tc.m, tc.needListener) 1803 fc := NewFrontendCompiler(tc.m, b, &offset, tc.ensureTermination, tc.needListener, false) 1804 typeIndex := tc.m.FunctionSection[tc.targetIndex] 1805 code := &tc.m.CodeSection[tc.targetIndex] 1806 fc.Init(tc.targetIndex, typeIndex, &tc.m.TypeSection[typeIndex], code.LocalTypes, code.Body, tc.needListener, 0) 1807 1808 fc.LowerToSSA() 1809 1810 actual := fc.formatBuilder() 1811 require.Equal(t, tc.exp, actual) 1812 1813 b.RunPasses() 1814 if expAfterOpt := tc.expAfterOpt; expAfterOpt != "" { 1815 actualAfterOpt := fc.formatBuilder() 1816 require.Equal(t, expAfterOpt, actualAfterOpt) 1817 } 1818 1819 // Dry-run without checking the results of LayoutBlocks function. 1820 b.LayoutBlocks() 1821 }) 1822 } 1823 } 1824 1825 func TestSignatureForListener(t *testing.T) { 1826 for _, tc := range []struct { 1827 name string 1828 sig *wasm.FunctionType 1829 before, after *ssa.Signature 1830 }{ 1831 { 1832 name: "empty", 1833 sig: &wasm.FunctionType{}, 1834 before: &ssa.Signature{Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}}, 1835 after: &ssa.Signature{Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}}, 1836 }, 1837 { 1838 name: "multi", 1839 sig: &wasm.FunctionType{ 1840 Params: []wasm.ValueType{wasm.ValueTypeF64, wasm.ValueTypeI32}, 1841 Results: []wasm.ValueType{ 1842 wasm.ValueTypeI64, wasm.ValueTypeI32, wasm.ValueTypeF32, wasm.ValueTypeF64, wasm.ValueTypeV128, 1843 }, 1844 }, 1845 before: &ssa.Signature{ 1846 Params: []ssa.Type{ 1847 ssa.TypeI64, ssa.TypeI32, 1848 ssa.TypeF64, ssa.TypeI32, 1849 }, 1850 }, 1851 after: &ssa.Signature{ 1852 Params: []ssa.Type{ 1853 ssa.TypeI64, ssa.TypeI32, 1854 ssa.TypeI64, ssa.TypeI32, ssa.TypeF32, ssa.TypeF64, ssa.TypeV128, 1855 }, 1856 }, 1857 }, 1858 } { 1859 tc := tc 1860 t.Run(tc.name, func(t *testing.T) { 1861 before, after := SignatureForListener(tc.sig) 1862 require.Equal(t, tc.before, before) 1863 require.Equal(t, tc.after, after) 1864 }) 1865 } 1866 } 1867 1868 func TestCompiler_declareSignatures(t *testing.T) { 1869 m := &wasm.Module{ 1870 TypeSection: []wasm.FunctionType{ 1871 {}, 1872 {Params: []wasm.ValueType{wasm.ValueTypeI64, wasm.ValueTypeI32}}, 1873 {Params: []wasm.ValueType{wasm.ValueTypeF64, wasm.ValueTypeI32}}, 1874 {Results: []wasm.ValueType{wasm.ValueTypeI64, wasm.ValueTypeI32}}, 1875 }, 1876 } 1877 1878 t.Run("listener=false", func(t *testing.T) { 1879 builder := ssa.NewBuilder() 1880 c := &Compiler{m: m, ssaBuilder: builder} 1881 c.declareSignatures(false) 1882 1883 declaredSigs := builder.Signatures() 1884 expected := []*ssa.Signature{ 1885 {ID: 0, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64}}, 1886 {ID: 1, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeI64, ssa.TypeI32}}, 1887 {ID: 2, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeF64, ssa.TypeI32}}, 1888 {ID: 3, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64}, Results: []ssa.Type{ssa.TypeI64, ssa.TypeI32}}, 1889 {ID: 4, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}, Results: []ssa.Type{ssa.TypeI32}}, 1890 {ID: 5, Params: []ssa.Type{ssa.TypeI64}}, 1891 {ID: 6, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32, ssa.TypeI32, ssa.TypeI64}, Results: []ssa.Type{ssa.TypeI32}}, 1892 {ID: 7, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}, Results: []ssa.Type{ssa.TypeI64}}, 1893 {ID: 8, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeI32}}, 1894 } 1895 1896 require.Equal(t, len(expected), len(declaredSigs)) 1897 for i := 0; i < len(expected); i++ { 1898 require.Equal(t, expected[i].String(), declaredSigs[i].String(), i) 1899 } 1900 }) 1901 1902 t.Run("listener=false", func(t *testing.T) { 1903 builder := ssa.NewBuilder() 1904 c := &Compiler{m: m, ssaBuilder: builder} 1905 c.declareSignatures(true) 1906 1907 declaredSigs := builder.Signatures() 1908 1909 expected := []*ssa.Signature{ 1910 {ID: 0, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64}}, 1911 {ID: 1, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeI64, ssa.TypeI32}}, 1912 {ID: 2, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeF64, ssa.TypeI32}}, 1913 {ID: 3, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64}, Results: []ssa.Type{ssa.TypeI64, ssa.TypeI32}}, 1914 // Before. 1915 {ID: 4, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}}, 1916 {ID: 5, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32, ssa.TypeI64, ssa.TypeI32}}, 1917 {ID: 6, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32, ssa.TypeF64, ssa.TypeI32}}, 1918 {ID: 7, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}}, 1919 // After. 1920 {ID: 8, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}}, 1921 {ID: 9, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}}, 1922 {ID: 10, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}}, 1923 {ID: 11, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32, ssa.TypeI64, ssa.TypeI32}}, 1924 // Misc. 1925 {ID: 12, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}, Results: []ssa.Type{ssa.TypeI32}}, 1926 {ID: 13, Params: []ssa.Type{ssa.TypeI64}}, 1927 {ID: 14, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32, ssa.TypeI32, ssa.TypeI64}, Results: []ssa.Type{ssa.TypeI32}}, 1928 {ID: 15, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}, Results: []ssa.Type{ssa.TypeI64}}, 1929 {ID: 16, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeI32}}, 1930 } 1931 require.Equal(t, len(expected), len(declaredSigs)) 1932 for i := 0; i < len(declaredSigs); i++ { 1933 require.Equal(t, expected[i].String(), declaredSigs[i].String(), i) 1934 } 1935 }) 1936 }