github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/internal/engine/wazevo/frontend/frontend_test.go (about) 1 package frontend 2 3 import ( 4 "testing" 5 6 "github.com/bananabytelabs/wazero/api" 7 "github.com/bananabytelabs/wazero/internal/engine/wazevo/ssa" 8 "github.com/bananabytelabs/wazero/internal/engine/wazevo/testcases" 9 "github.com/bananabytelabs/wazero/internal/engine/wazevo/wazevoapi" 10 "github.com/bananabytelabs/wazero/internal/testing/require" 11 "github.com/bananabytelabs/wazero/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:i32 = Load v10, 0x0 1023 Jump blk_ret, v11 1024 `, 1025 }, 1026 { 1027 name: "memory_load_basic", m: testcases.MemoryLoadBasic.Module, 1028 exp: ` 1029 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 1030 v3:i64 = Iconst_64 0x4 1031 v4:i64 = UExtend v2, 32->64 1032 v5:i64 = Uload32 module_ctx, 0x10 1033 v6:i64 = Iadd v4, v3 1034 v7:i32 = Icmp lt_u, v5, v6 1035 ExitIfTrue v7, exec_ctx, memory_out_of_bounds 1036 v8:i64 = Load module_ctx, 0x8 1037 v9:i64 = Iadd v8, v4 1038 v10:i32 = Load v9, 0x0 1039 Jump blk_ret, v10 1040 `, 1041 }, 1042 { 1043 name: "memory_load_basic2", m: testcases.MemoryLoadBasic2.Module, 1044 exp: ` 1045 signatures: 1046 sig1: i64i64_v 1047 1048 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 1049 v3:i32 = Iconst_32 0x0 1050 v4:i32 = Icmp eq, v2, v3 1051 Brz v4, blk2 1052 Jump blk1 1053 1054 blk1: () <-- (blk0) 1055 Store module_ctx, exec_ctx, 0x8 1056 Call f1:sig1, exec_ctx, module_ctx 1057 v5:i64 = Load module_ctx, 0x8 1058 v6:i64 = Uload32 module_ctx, 0x10 1059 Jump blk3, v2 1060 1061 blk2: () <-- (blk0) 1062 Jump blk3, v2 1063 1064 blk3: (v7:i32) <-- (blk1,blk2) 1065 v8:i64 = Iconst_64 0x4 1066 v9:i64 = UExtend v7, 32->64 1067 v10:i64 = Uload32 module_ctx, 0x10 1068 v11:i64 = Iadd v9, v8 1069 v12:i32 = Icmp lt_u, v10, v11 1070 ExitIfTrue v12, exec_ctx, memory_out_of_bounds 1071 v13:i64 = Load module_ctx, 0x8 1072 v14:i64 = Iadd v13, v9 1073 v15:i32 = Load v14, 0x0 1074 Jump blk_ret, v15 1075 `, 1076 expAfterOpt: ` 1077 signatures: 1078 sig1: i64i64_v 1079 1080 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 1081 v3:i32 = Iconst_32 0x0 1082 v4:i32 = Icmp eq, v2, v3 1083 Brz v4, blk2 1084 Jump blk1 1085 1086 blk1: () <-- (blk0) 1087 Store module_ctx, exec_ctx, 0x8 1088 Call f1:sig1, exec_ctx, module_ctx 1089 Jump blk3 1090 1091 blk2: () <-- (blk0) 1092 Jump blk3 1093 1094 blk3: () <-- (blk1,blk2) 1095 v8:i64 = Iconst_64 0x4 1096 v9:i64 = UExtend v2, 32->64 1097 v10:i64 = Uload32 module_ctx, 0x10 1098 v11:i64 = Iadd v9, v8 1099 v12:i32 = Icmp lt_u, v10, v11 1100 ExitIfTrue v12, exec_ctx, memory_out_of_bounds 1101 v13:i64 = Load module_ctx, 0x8 1102 v14:i64 = Iadd v13, v9 1103 v15:i32 = Load v14, 0x0 1104 Jump blk_ret, v15 1105 `, 1106 }, 1107 { 1108 name: "imported_function_call", m: testcases.ImportedFunctionCall.Module, 1109 exp: ` 1110 signatures: 1111 sig1: i64i64i32i32_i32 1112 1113 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 1114 Store module_ctx, exec_ctx, 0x8 1115 v3:i64 = Load module_ctx, 0x8 1116 v4:i64 = Load module_ctx, 0x10 1117 v5:i32 = CallIndirect v3:sig1, exec_ctx, v4, v2, v2 1118 Jump blk_ret, v5 1119 `, 1120 }, 1121 { 1122 name: "memory_loads", m: testcases.MemoryLoads.Module, 1123 exp: ` 1124 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 1125 v3:i64 = Iconst_64 0x4 1126 v4:i64 = UExtend v2, 32->64 1127 v5:i64 = Uload32 module_ctx, 0x10 1128 v6:i64 = Iadd v4, v3 1129 v7:i32 = Icmp lt_u, v5, v6 1130 ExitIfTrue v7, exec_ctx, memory_out_of_bounds 1131 v8:i64 = Load module_ctx, 0x8 1132 v9:i64 = Iadd v8, v4 1133 v10:i32 = Load v9, 0x0 1134 v11:i64 = Iconst_64 0x8 1135 v12:i64 = UExtend v2, 32->64 1136 v13:i64 = Iadd v12, v11 1137 v14:i32 = Icmp lt_u, v5, v13 1138 ExitIfTrue v14, exec_ctx, memory_out_of_bounds 1139 v15:i64 = Load v9, 0x0 1140 v16:f32 = Load v9, 0x0 1141 v17:f64 = Load v9, 0x0 1142 v18:i64 = Iconst_64 0x13 1143 v19:i64 = UExtend v2, 32->64 1144 v20:i64 = Iadd v19, v18 1145 v21:i32 = Icmp lt_u, v5, v20 1146 ExitIfTrue v21, exec_ctx, memory_out_of_bounds 1147 v22:i32 = Load v9, 0xf 1148 v23:i64 = Iconst_64 0x17 1149 v24:i64 = UExtend v2, 32->64 1150 v25:i64 = Iadd v24, v23 1151 v26:i32 = Icmp lt_u, v5, v25 1152 ExitIfTrue v26, exec_ctx, memory_out_of_bounds 1153 v27:i64 = Load v9, 0xf 1154 v28:f32 = Load v9, 0xf 1155 v29:f64 = Load v9, 0xf 1156 v30:i32 = Sload8 v9, 0x0 1157 v31:i32 = Sload8 v9, 0xf 1158 v32:i32 = Uload8 v9, 0x0 1159 v33:i32 = Uload8 v9, 0xf 1160 v34:i32 = Sload16 v9, 0x0 1161 v35:i32 = Sload16 v9, 0xf 1162 v36:i32 = Uload16 v9, 0x0 1163 v37:i32 = Uload16 v9, 0xf 1164 v38:i64 = Sload8 v9, 0x0 1165 v39:i64 = Sload8 v9, 0xf 1166 v40:i64 = Uload8 v9, 0x0 1167 v41:i64 = Uload8 v9, 0xf 1168 v42:i64 = Sload16 v9, 0x0 1169 v43:i64 = Sload16 v9, 0xf 1170 v44:i64 = Uload16 v9, 0x0 1171 v45:i64 = Uload16 v9, 0xf 1172 v46:i64 = Sload32 v9, 0x0 1173 v47:i64 = Sload32 v9, 0xf 1174 v48:i64 = Uload32 v9, 0x0 1175 v49:i64 = Uload32 v9, 0xf 1176 Jump blk_ret, v10, v15, v16, v17, v22, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49 1177 `, 1178 }, 1179 { 1180 name: "globals_get", 1181 m: testcases.GlobalsGet.Module, 1182 exp: ` 1183 blk0: (exec_ctx:i64, module_ctx:i64) 1184 v2:i32 = Load module_ctx, 0x8 1185 v3:i64 = Load module_ctx, 0x18 1186 v4:f32 = Load module_ctx, 0x28 1187 v5:f64 = Load module_ctx, 0x38 1188 Jump blk_ret, v2, v3, v4, v5 1189 `, 1190 }, 1191 { 1192 name: "globals_set", 1193 m: testcases.GlobalsSet.Module, 1194 exp: ` 1195 blk0: (exec_ctx:i64, module_ctx:i64) 1196 v2:i32 = Iconst_32 0x1 1197 Store v2, module_ctx, 0x8 1198 v3:i64 = Iconst_64 0x2 1199 Store v3, module_ctx, 0x18 1200 v4:f32 = F32const 3.000000 1201 Store v4, module_ctx, 0x28 1202 v5:f64 = F64const 4.000000 1203 Store v5, module_ctx, 0x38 1204 Jump blk_ret, v2, v3, v4, v5 1205 `, 1206 }, 1207 { 1208 name: "globals_mutable", 1209 m: testcases.GlobalsMutable.Module, 1210 exp: ` 1211 signatures: 1212 sig1: i64i64_v 1213 1214 blk0: (exec_ctx:i64, module_ctx:i64) 1215 v2:i32 = Load module_ctx, 0x8 1216 v3:i64 = Load module_ctx, 0x18 1217 v4:f32 = Load module_ctx, 0x28 1218 v5:f64 = Load module_ctx, 0x38 1219 Store module_ctx, exec_ctx, 0x8 1220 Call f1:sig1, exec_ctx, module_ctx 1221 v6:i32 = Load module_ctx, 0x8 1222 v7:i64 = Load module_ctx, 0x18 1223 v8:f32 = Load module_ctx, 0x28 1224 v9:f64 = Load module_ctx, 0x38 1225 Jump blk_ret, v2, v3, v4, v5, v6, v7, v8, v9 1226 `, 1227 expAfterOpt: ` 1228 signatures: 1229 sig1: i64i64_v 1230 1231 blk0: (exec_ctx:i64, module_ctx:i64) 1232 v2:i32 = Load module_ctx, 0x8 1233 v3:i64 = Load module_ctx, 0x18 1234 v4:f32 = Load module_ctx, 0x28 1235 v5:f64 = Load module_ctx, 0x38 1236 Store module_ctx, exec_ctx, 0x8 1237 Call f1:sig1, exec_ctx, module_ctx 1238 v6:i32 = Load module_ctx, 0x8 1239 v7:i64 = Load module_ctx, 0x18 1240 v8:f32 = Load module_ctx, 0x28 1241 v9:f64 = Load module_ctx, 0x38 1242 Jump blk_ret, v2, v3, v4, v5, v6, v7, v8, v9 1243 `, 1244 }, 1245 { 1246 name: "imported_memory_grow", 1247 m: testcases.ImportedMemoryGrow.Module, 1248 exp: ` 1249 signatures: 1250 sig0: i64i64_i32 1251 sig2: i64i32_i32 1252 1253 blk0: (exec_ctx:i64, module_ctx:i64) 1254 Store module_ctx, exec_ctx, 0x8 1255 v2:i64 = Load module_ctx, 0x18 1256 v3:i64 = Load module_ctx, 0x20 1257 v4:i32 = CallIndirect v2:sig0, exec_ctx, v3 1258 v5:i64 = Load module_ctx, 0x8 1259 v6:i64 = Load v5, 0x0 1260 v7:i64 = Load module_ctx, 0x8 1261 v8:i64 = Load v7, 0x8 1262 v9:i64 = Load module_ctx, 0x8 1263 v10:i32 = Load v9, 0x8 1264 v11:i32 = Iconst_32 0x10 1265 v12:i32 = Ushr v10, v11 1266 v13:i32 = Iconst_32 0xa 1267 Store module_ctx, exec_ctx, 0x8 1268 v14:i64 = Load exec_ctx, 0x48 1269 v15:i32 = CallIndirect v14:sig2, exec_ctx, v13 1270 v16:i64 = Load module_ctx, 0x8 1271 v17:i64 = Load v16, 0x0 1272 v18:i64 = Load module_ctx, 0x8 1273 v19:i64 = Load v18, 0x8 1274 Store module_ctx, exec_ctx, 0x8 1275 v20:i64 = Load module_ctx, 0x18 1276 v21:i64 = Load module_ctx, 0x20 1277 v22:i32 = CallIndirect v20:sig0, exec_ctx, v21 1278 v23:i64 = Load module_ctx, 0x8 1279 v24:i64 = Load v23, 0x0 1280 v25:i64 = Load module_ctx, 0x8 1281 v26:i64 = Load v25, 0x8 1282 v27:i64 = Load module_ctx, 0x8 1283 v28:i32 = Load v27, 0x8 1284 v29:i32 = Iconst_32 0x10 1285 v30:i32 = Ushr v28, v29 1286 Jump blk_ret, v4, v12, v22, v30 1287 `, 1288 expAfterOpt: ` 1289 signatures: 1290 sig0: i64i64_i32 1291 sig2: i64i32_i32 1292 1293 blk0: (exec_ctx:i64, module_ctx:i64) 1294 Store module_ctx, exec_ctx, 0x8 1295 v2:i64 = Load module_ctx, 0x18 1296 v3:i64 = Load module_ctx, 0x20 1297 v4:i32 = CallIndirect v2:sig0, exec_ctx, v3 1298 v9:i64 = Load module_ctx, 0x8 1299 v10:i32 = Load v9, 0x8 1300 v11:i32 = Iconst_32 0x10 1301 v12:i32 = Ushr v10, v11 1302 v13:i32 = Iconst_32 0xa 1303 Store module_ctx, exec_ctx, 0x8 1304 v14:i64 = Load exec_ctx, 0x48 1305 v15:i32 = CallIndirect v14:sig2, exec_ctx, v13 1306 Store module_ctx, exec_ctx, 0x8 1307 v20:i64 = Load module_ctx, 0x18 1308 v21:i64 = Load module_ctx, 0x20 1309 v22:i32 = CallIndirect v20:sig0, exec_ctx, v21 1310 v27:i64 = Load module_ctx, 0x8 1311 v28:i32 = Load v27, 0x8 1312 v29:i32 = Iconst_32 0x10 1313 v30:i32 = Ushr v28, v29 1314 Jump blk_ret, v4, v12, v22, v30 1315 `, 1316 }, 1317 { 1318 name: "memory_size_grow", 1319 m: testcases.MemorySizeGrow.Module, 1320 exp: ` 1321 signatures: 1322 sig1: i64i32_i32 1323 1324 blk0: (exec_ctx:i64, module_ctx:i64) 1325 v2:i32 = Iconst_32 0x1 1326 Store module_ctx, exec_ctx, 0x8 1327 v3:i64 = Load exec_ctx, 0x48 1328 v4:i32 = CallIndirect v3:sig1, exec_ctx, v2 1329 v5:i64 = Load module_ctx, 0x8 1330 v6:i64 = Uload32 module_ctx, 0x10 1331 v7:i32 = Load module_ctx, 0x10 1332 v8:i32 = Iconst_32 0x10 1333 v9:i32 = Ushr v7, v8 1334 v10:i32 = Iconst_32 0x1 1335 Store module_ctx, exec_ctx, 0x8 1336 v11:i64 = Load exec_ctx, 0x48 1337 v12:i32 = CallIndirect v11:sig1, exec_ctx, v10 1338 v13:i64 = Load module_ctx, 0x8 1339 v14:i64 = Uload32 module_ctx, 0x10 1340 Jump blk_ret, v4, v9, v12 1341 `, 1342 expAfterOpt: ` 1343 signatures: 1344 sig1: i64i32_i32 1345 1346 blk0: (exec_ctx:i64, module_ctx:i64) 1347 v2:i32 = Iconst_32 0x1 1348 Store module_ctx, exec_ctx, 0x8 1349 v3:i64 = Load exec_ctx, 0x48 1350 v4:i32 = CallIndirect v3:sig1, exec_ctx, v2 1351 v7:i32 = Load module_ctx, 0x10 1352 v8:i32 = Iconst_32 0x10 1353 v9:i32 = Ushr v7, v8 1354 v10:i32 = Iconst_32 0x1 1355 Store module_ctx, exec_ctx, 0x8 1356 v11:i64 = Load exec_ctx, 0x48 1357 v12:i32 = CallIndirect v11:sig1, exec_ctx, v10 1358 Jump blk_ret, v4, v9, v12 1359 `, 1360 }, 1361 { 1362 name: "call_indirect", m: testcases.CallIndirect.Module, 1363 exp: ` 1364 signatures: 1365 sig2: i64i64_i32 1366 1367 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 1368 v3:i64 = Load module_ctx, 0x10 1369 v4:i32 = Load v3, 0x8 1370 v5:i32 = Icmp ge_u, v2, v4 1371 ExitIfTrue v5, exec_ctx, table_out_of_bounds 1372 v6:i64 = Load v3, 0x0 1373 v7:i64 = Iconst_64 0x3 1374 v8:i32 = Ishl v2, v7 1375 v9:i64 = Iadd v6, v8 1376 v10:i64 = Load v9, 0x0 1377 v11:i64 = Iconst_64 0x0 1378 v12:i32 = Icmp eq, v10, v11 1379 ExitIfTrue v12, exec_ctx, indirect_call_null_pointer 1380 v13:i32 = Load v10, 0x10 1381 v14:i64 = Load module_ctx, 0x8 1382 v15:i32 = Load v14, 0x8 1383 v16:i32 = Icmp neq, v13, v15 1384 ExitIfTrue v16, exec_ctx, indirect_call_type_mismatch 1385 v17:i64 = Load v10, 0x0 1386 v18:i64 = Load v10, 0x8 1387 Store module_ctx, exec_ctx, 0x8 1388 v19:i32 = CallIndirect v17:sig2, exec_ctx, v18 1389 Jump blk_ret, v19 1390 `, 1391 }, 1392 { 1393 name: "br_table", m: testcases.BrTable.Module, 1394 exp: ` 1395 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32) 1396 BrTable v2, [blk7, blk8, blk9, blk10, blk11, blk12, blk13] 1397 1398 blk1: () <-- (blk12) 1399 v8:i32 = Iconst_32 0x10 1400 Return v8 1401 1402 blk2: () <-- (blk11) 1403 v7:i32 = Iconst_32 0xf 1404 Return v7 1405 1406 blk3: () <-- (blk10) 1407 v6:i32 = Iconst_32 0xe 1408 Return v6 1409 1410 blk4: () <-- (blk9) 1411 v5:i32 = Iconst_32 0xd 1412 Return v5 1413 1414 blk5: () <-- (blk8) 1415 v4:i32 = Iconst_32 0xc 1416 Return v4 1417 1418 blk6: () <-- (blk7,blk13) 1419 v3:i32 = Iconst_32 0xb 1420 Return v3 1421 1422 blk7: () <-- (blk0) 1423 Jump blk6 1424 1425 blk8: () <-- (blk0) 1426 Jump blk5 1427 1428 blk9: () <-- (blk0) 1429 Jump blk4 1430 1431 blk10: () <-- (blk0) 1432 Jump blk3 1433 1434 blk11: () <-- (blk0) 1435 Jump blk2 1436 1437 blk12: () <-- (blk0) 1438 Jump blk1 1439 1440 blk13: () <-- (blk0) 1441 Jump blk6 1442 `, 1443 }, 1444 { 1445 name: "br_table_with_arg", m: testcases.BrTableWithArg.Module, 1446 exp: ` 1447 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32) 1448 BrTable v2, [blk7, blk8, blk9, blk10, blk11, blk12, blk13] 1449 1450 blk1: (v4:i32) <-- (blk12) 1451 v20:i32 = Iconst_32 0x10 1452 v21:i32 = Iadd v4, v20 1453 Return v21 1454 1455 blk2: (v5:i32) <-- (blk11) 1456 v18:i32 = Iconst_32 0xf 1457 v19:i32 = Iadd v5, v18 1458 Return v19 1459 1460 blk3: (v6:i32) <-- (blk10) 1461 v16:i32 = Iconst_32 0xe 1462 v17:i32 = Iadd v6, v16 1463 Return v17 1464 1465 blk4: (v7:i32) <-- (blk9) 1466 v14:i32 = Iconst_32 0xd 1467 v15:i32 = Iadd v7, v14 1468 Return v15 1469 1470 blk5: (v8:i32) <-- (blk8) 1471 v12:i32 = Iconst_32 0xc 1472 v13:i32 = Iadd v8, v12 1473 Return v13 1474 1475 blk6: (v9:i32) <-- (blk7,blk13) 1476 v10:i32 = Iconst_32 0xb 1477 v11:i32 = Iadd v9, v10 1478 Return v11 1479 1480 blk7: () <-- (blk0) 1481 Jump blk6, v3 1482 1483 blk8: () <-- (blk0) 1484 Jump blk5, v3 1485 1486 blk9: () <-- (blk0) 1487 Jump blk4, v3 1488 1489 blk10: () <-- (blk0) 1490 Jump blk3, v3 1491 1492 blk11: () <-- (blk0) 1493 Jump blk2, v3 1494 1495 blk12: () <-- (blk0) 1496 Jump blk1, v3 1497 1498 blk13: () <-- (blk0) 1499 Jump blk6, v3 1500 `, 1501 1502 // TODO: these trivial two hop jumps should be optimized away. 1503 expAfterOpt: ` 1504 blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32) 1505 BrTable v2, [blk7, blk8, blk9, blk10, blk11, blk12, blk13] 1506 1507 blk1: () <-- (blk12) 1508 v20:i32 = Iconst_32 0x10 1509 v21:i32 = Iadd v3, v20 1510 Return v21 1511 1512 blk2: () <-- (blk11) 1513 v18:i32 = Iconst_32 0xf 1514 v19:i32 = Iadd v3, v18 1515 Return v19 1516 1517 blk3: () <-- (blk10) 1518 v16:i32 = Iconst_32 0xe 1519 v17:i32 = Iadd v3, v16 1520 Return v17 1521 1522 blk4: () <-- (blk9) 1523 v14:i32 = Iconst_32 0xd 1524 v15:i32 = Iadd v3, v14 1525 Return v15 1526 1527 blk5: () <-- (blk8) 1528 v12:i32 = Iconst_32 0xc 1529 v13:i32 = Iadd v3, v12 1530 Return v13 1531 1532 blk6: () <-- (blk7,blk13) 1533 v10:i32 = Iconst_32 0xb 1534 v11:i32 = Iadd v3, v10 1535 Return v11 1536 1537 blk7: () <-- (blk0) 1538 Jump blk6 1539 1540 blk8: () <-- (blk0) 1541 Jump blk5 1542 1543 blk9: () <-- (blk0) 1544 Jump blk4 1545 1546 blk10: () <-- (blk0) 1547 Jump blk3 1548 1549 blk11: () <-- (blk0) 1550 Jump blk2 1551 1552 blk12: () <-- (blk0) 1553 Jump blk1 1554 1555 blk13: () <-- (blk0) 1556 Jump blk6 1557 `, 1558 }, 1559 { 1560 name: "if_then_end_nesting_unreachable_if_then_else_end", m: testcases.IfThenEndNestingUnreachableIfThenElseEnd.Module, 1561 exp: ` 1562 blk0: (exec_ctx:i64, module_ctx:i64, v2:f64, v3:f64, v4:f64) 1563 v6:i32 = Load module_ctx, 0x10 1564 v7:i32 = Iconst_32 0x10 1565 v8:i32 = Ushr v6, v7 1566 Brz v8, blk3 1567 Jump blk2 1568 1569 blk1: (v5:i64) <-- (blk4) 1570 Jump blk_ret 1571 1572 blk2: () <-- (blk0) 1573 v9:i32 = Load module_ctx, 0x10 1574 v10:i32 = Iconst_32 0x10 1575 v11:i32 = Ushr v9, v10 1576 Jump blk4 1577 1578 blk3: () <-- (blk0) 1579 Jump blk4 1580 1581 blk4: () <-- (blk2,blk3) 1582 v12:i64 = Iconst_64 0x0 1583 Jump blk1, v12 1584 `, 1585 expAfterOpt: ` 1586 blk0: (exec_ctx:i64, module_ctx:i64, v2:f64, v3:f64, v4:f64) 1587 v6:i32 = Load module_ctx, 0x10 1588 v7:i32 = Iconst_32 0x10 1589 v8:i32 = Ushr v6, v7 1590 Brz v8, blk3 1591 Jump blk2 1592 1593 blk1: () <-- (blk4) 1594 Jump blk_ret 1595 1596 blk2: () <-- (blk0) 1597 Jump blk4 1598 1599 blk3: () <-- (blk0) 1600 Jump blk4 1601 1602 blk4: () <-- (blk2,blk3) 1603 Jump blk1 1604 `, 1605 }, 1606 { 1607 name: "VecShuffle", 1608 m: testcases.VecShuffle.Module, 1609 exp: ` 1610 blk0: (exec_ctx:i64, module_ctx:i64, v2:v128, v3:v128) 1611 v4:v128 = Shuffle.[0 1 2 3 4 5 6 7 24 25 26 27 28 29 30 31] v2, v3 1612 Jump blk_ret, v4 1613 `, 1614 }, 1615 } { 1616 1617 tc := tc 1618 t.Run(tc.name, func(t *testing.T) { 1619 // Just in case let's check the test module is valid. 1620 err := tc.m.Validate(api.CoreFeaturesV2) 1621 require.NoError(t, err, "invalid test case module!") 1622 1623 b := ssa.NewBuilder() 1624 1625 offset := wazevoapi.NewModuleContextOffsetData(tc.m, tc.needListener) 1626 fc := NewFrontendCompiler(tc.m, b, &offset, tc.ensureTermination, tc.needListener, false) 1627 typeIndex := tc.m.FunctionSection[tc.targetIndex] 1628 code := &tc.m.CodeSection[tc.targetIndex] 1629 fc.Init(tc.targetIndex, typeIndex, &tc.m.TypeSection[typeIndex], code.LocalTypes, code.Body, tc.needListener, 0) 1630 1631 fc.LowerToSSA() 1632 1633 actual := fc.formatBuilder() 1634 require.Equal(t, tc.exp, actual) 1635 1636 b.RunPasses() 1637 if expAfterOpt := tc.expAfterOpt; expAfterOpt != "" { 1638 actualAfterOpt := fc.formatBuilder() 1639 require.Equal(t, expAfterOpt, actualAfterOpt) 1640 } 1641 1642 // Dry-run without checking the results of LayoutBlocks function. 1643 b.LayoutBlocks() 1644 }) 1645 } 1646 } 1647 1648 func TestSignatureForListener(t *testing.T) { 1649 for _, tc := range []struct { 1650 name string 1651 sig *wasm.FunctionType 1652 before, after *ssa.Signature 1653 }{ 1654 { 1655 name: "empty", 1656 sig: &wasm.FunctionType{}, 1657 before: &ssa.Signature{Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}}, 1658 after: &ssa.Signature{Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}}, 1659 }, 1660 { 1661 name: "multi", 1662 sig: &wasm.FunctionType{ 1663 Params: []wasm.ValueType{wasm.ValueTypeF64, wasm.ValueTypeI32}, 1664 Results: []wasm.ValueType{ 1665 wasm.ValueTypeI64, wasm.ValueTypeI32, wasm.ValueTypeF32, wasm.ValueTypeF64, wasm.ValueTypeV128, 1666 }, 1667 }, 1668 before: &ssa.Signature{ 1669 Params: []ssa.Type{ 1670 ssa.TypeI64, ssa.TypeI32, 1671 ssa.TypeF64, ssa.TypeI32, 1672 }, 1673 }, 1674 after: &ssa.Signature{ 1675 Params: []ssa.Type{ 1676 ssa.TypeI64, ssa.TypeI32, 1677 ssa.TypeI64, ssa.TypeI32, ssa.TypeF32, ssa.TypeF64, ssa.TypeV128, 1678 }, 1679 }, 1680 }, 1681 } { 1682 tc := tc 1683 t.Run(tc.name, func(t *testing.T) { 1684 before, after := SignatureForListener(tc.sig) 1685 require.Equal(t, tc.before, before) 1686 require.Equal(t, tc.after, after) 1687 }) 1688 } 1689 } 1690 1691 func TestCompiler_declareSignatures(t *testing.T) { 1692 m := &wasm.Module{ 1693 TypeSection: []wasm.FunctionType{ 1694 {}, 1695 {Params: []wasm.ValueType{wasm.ValueTypeI64, wasm.ValueTypeI32}}, 1696 {Params: []wasm.ValueType{wasm.ValueTypeF64, wasm.ValueTypeI32}}, 1697 {Results: []wasm.ValueType{wasm.ValueTypeI64, wasm.ValueTypeI32}}, 1698 }, 1699 } 1700 1701 t.Run("listener=false", func(t *testing.T) { 1702 builder := ssa.NewBuilder() 1703 c := &Compiler{m: m, ssaBuilder: builder} 1704 c.declareSignatures(false) 1705 1706 declaredSigs := builder.Signatures() 1707 expected := []*ssa.Signature{ 1708 {ID: 0, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64}}, 1709 {ID: 1, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeI64, ssa.TypeI32}}, 1710 {ID: 2, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeF64, ssa.TypeI32}}, 1711 {ID: 3, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64}, Results: []ssa.Type{ssa.TypeI64, ssa.TypeI32}}, 1712 {ID: 4, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}, Results: []ssa.Type{ssa.TypeI32}}, 1713 {ID: 5, Params: []ssa.Type{ssa.TypeI64}}, 1714 {ID: 6, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32, ssa.TypeI32, ssa.TypeI64}, Results: []ssa.Type{ssa.TypeI32}}, 1715 {ID: 7, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}, Results: []ssa.Type{ssa.TypeI64}}, 1716 {ID: 8, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeI32}}, 1717 } 1718 1719 require.Equal(t, len(expected), len(declaredSigs)) 1720 for i := 0; i < len(expected); i++ { 1721 require.Equal(t, expected[i].String(), declaredSigs[i].String(), i) 1722 } 1723 }) 1724 1725 t.Run("listener=false", func(t *testing.T) { 1726 builder := ssa.NewBuilder() 1727 c := &Compiler{m: m, ssaBuilder: builder} 1728 c.declareSignatures(true) 1729 1730 declaredSigs := builder.Signatures() 1731 1732 expected := []*ssa.Signature{ 1733 {ID: 0, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64}}, 1734 {ID: 1, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeI64, ssa.TypeI32}}, 1735 {ID: 2, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeF64, ssa.TypeI32}}, 1736 {ID: 3, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64}, Results: []ssa.Type{ssa.TypeI64, ssa.TypeI32}}, 1737 // Before. 1738 {ID: 4, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}}, 1739 {ID: 5, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32, ssa.TypeI64, ssa.TypeI32}}, 1740 {ID: 6, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32, ssa.TypeF64, ssa.TypeI32}}, 1741 {ID: 7, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}}, 1742 // After. 1743 {ID: 8, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}}, 1744 {ID: 9, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}}, 1745 {ID: 10, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}}, 1746 {ID: 11, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32, ssa.TypeI64, ssa.TypeI32}}, 1747 // Misc. 1748 {ID: 12, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}, Results: []ssa.Type{ssa.TypeI32}}, 1749 {ID: 13, Params: []ssa.Type{ssa.TypeI64}}, 1750 {ID: 14, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32, ssa.TypeI32, ssa.TypeI64}, Results: []ssa.Type{ssa.TypeI32}}, 1751 {ID: 15, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}, Results: []ssa.Type{ssa.TypeI64}}, 1752 {ID: 16, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeI32}}, 1753 } 1754 require.Equal(t, len(expected), len(declaredSigs)) 1755 for i := 0; i < len(declaredSigs); i++ { 1756 require.Equal(t, expected[i].String(), declaredSigs[i].String(), i) 1757 } 1758 }) 1759 } 1760 1761 func TestCompiler_recordKnownSafeBound(t *testing.T) { 1762 c := &Compiler{} 1763 c.recordKnownSafeBound(1, 99, 9999) 1764 require.Equal(t, 1, len(c.knownSafeBoundsSet)) 1765 require.True(t, c.getKnownSafeBound(1).valid()) 1766 require.Equal(t, uint64(99), c.getKnownSafeBound(1).bound) 1767 require.Equal(t, ssa.Value(9999), c.getKnownSafeBound(1).absoluteAddr) 1768 1769 c.recordKnownSafeBound(1, 150, 9999) 1770 require.Equal(t, 1, len(c.knownSafeBoundsSet)) 1771 require.Equal(t, uint64(150), c.getKnownSafeBound(1).bound) 1772 1773 c.recordKnownSafeBound(5, 666, 54321) 1774 require.Equal(t, 2, len(c.knownSafeBoundsSet)) 1775 require.Equal(t, uint64(666), c.getKnownSafeBound(5).bound) 1776 require.Equal(t, ssa.Value(54321), c.getKnownSafeBound(5).absoluteAddr) 1777 } 1778 1779 func TestCompiler_getKnownSafeBound(t *testing.T) { 1780 c := &Compiler{ 1781 knownSafeBounds: []knownSafeBound{ 1782 {}, {bound: 2134}, 1783 }, 1784 } 1785 require.Nil(t, c.getKnownSafeBound(5)) 1786 require.Nil(t, c.getKnownSafeBound(12345)) 1787 require.False(t, c.getKnownSafeBound(0).valid()) 1788 require.True(t, c.getKnownSafeBound(1).valid()) 1789 } 1790 1791 func TestCompiler_clearSafeBounds(t *testing.T) { 1792 c := &Compiler{} 1793 c.knownSafeBounds = []knownSafeBound{{bound: 1}, {}, {bound: 2}, {}, {}, {bound: 3}} 1794 c.knownSafeBoundsSet = []ssa.ValueID{0, 2, 5} 1795 c.clearSafeBounds() 1796 require.Equal(t, 0, len(c.knownSafeBoundsSet)) 1797 require.Equal(t, []knownSafeBound{{}, {}, {}, {}, {}, {}}, c.knownSafeBounds) 1798 } 1799 1800 func TestKnownSafeBound_valid(t *testing.T) { 1801 k := &knownSafeBound{bound: 10, absoluteAddr: 12345} 1802 require.True(t, k.valid()) 1803 k.bound = 0 1804 require.False(t, k.valid()) 1805 }