1 //=== WebAssemblyExceptionInfoTest.cpp - WebAssebmlyExceptionInfo unit tests =// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "WebAssemblyExceptionInfo.h" 11 #include "llvm/CodeGen/MIRParser/MIRParser.h" 12 #include "llvm/CodeGen/MachineDominanceFrontier.h" 13 #include "llvm/CodeGen/MachineDominators.h" 14 #include "llvm/CodeGen/MachineModuleInfo.h" 15 #include "llvm/Support/SourceMgr.h" 16 #include "llvm/Support/TargetRegistry.h" 17 #include "llvm/Support/TargetSelect.h" 18 #include "llvm/Target/TargetMachine.h" 19 #include "gtest/gtest.h" 20 21 using namespace llvm; 22 23 namespace { 24 25 std::unique_ptr<LLVMTargetMachine> createTargetMachine() { 26 auto TT(Triple::normalize("wasm32-unknown-unknown")); 27 std::string CPU(""); 28 std::string FS(""); 29 30 LLVMInitializeWebAssemblyTargetInfo(); 31 LLVMInitializeWebAssemblyTarget(); 32 LLVMInitializeWebAssemblyTargetMC(); 33 34 std::string Error; 35 const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error); 36 assert(TheTarget); 37 38 return std::unique_ptr<LLVMTargetMachine>(static_cast<LLVMTargetMachine*>( 39 TheTarget->createTargetMachine(TT, CPU, FS, TargetOptions(), None, None, 40 CodeGenOpt::Default))); 41 } 42 43 std::unique_ptr<Module> parseMIR(LLVMContext &Context, 44 std::unique_ptr<MIRParser> &MIR, 45 const TargetMachine &TM, StringRef MIRCode, 46 const char *FuncName, MachineModuleInfo &MMI) { 47 SMDiagnostic Diagnostic; 48 std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRCode); 49 MIR = createMIRParser(std::move(MBuffer), Context); 50 if (!MIR) 51 return nullptr; 52 53 std::unique_ptr<Module> M = MIR->parseIRModule(); 54 if (!M) 55 return nullptr; 56 57 M->setDataLayout(TM.createDataLayout()); 58 59 if (MIR->parseMachineFunctions(*M, MMI)) 60 return nullptr; 61 62 return M; 63 } 64 65 } // namespace 66 67 TEST(WebAssemblyExceptionInfoTest, TEST0) { 68 std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine(); 69 ASSERT_TRUE(TM); 70 71 StringRef MIRString = R"MIR( 72 --- | 73 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" 74 target triple = "wasm32-unknown-unknown" 75 76 declare i32 @__gxx_wasm_personality_v0(...) 77 78 define hidden void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { 79 unreachable 80 } 81 82 ... 83 --- 84 name: test0 85 liveins: 86 - { reg: '$arguments' } 87 - { reg: '$value_stack' } 88 body: | 89 bb.0: 90 successors: %bb.1, %bb.2 91 liveins: $arguments, $value_stack 92 BR %bb.1, implicit-def dead $arguments 93 94 bb.1: 95 ; predecessors: %bb.0 96 successors: %bb.7 97 liveins: $value_stack 98 BR %bb.7, implicit-def $arguments 99 100 bb.2 (landing-pad): 101 ; predecessors: %bb.0 102 successors: %bb.3, %bb.9 103 liveins: $value_stack 104 CATCH_ALL implicit-def $arguments 105 CLEANUPRET implicit-def dead $arguments 106 107 bb.3 (landing-pad): 108 ; predecessors: %bb.2 109 successors: %bb.4, %bb.6 110 liveins: $value_stack 111 CATCH_ALL implicit-def $arguments 112 BR_IF %bb.4, %58:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack 113 BR %bb.6, implicit-def $arguments 114 115 bb.4: 116 ; predecessors: %bb.3 117 successors: %bb.5, %bb.8 118 liveins: $value_stack 119 BR %bb.5, implicit-def dead $arguments 120 121 bb.5: 122 ; predecessors: %bb.4 123 successors: %bb.7 124 liveins: $value_stack 125 CATCHRET %bb.7, %bb.0, implicit-def dead $arguments 126 127 bb.6: 128 ; predecessors: %bb.3 129 successors: %bb.10, %bb.9 130 liveins: $value_stack 131 BR %bb.10, implicit-def dead $arguments 132 133 bb.7: 134 ; predecessors: %bb.5, %bb.1 135 liveins: $value_stack 136 RETURN_VOID implicit-def $arguments 137 138 bb.8 (landing-pad): 139 ; predecessors: %bb.4 140 successors: %bb.9 141 liveins: $value_stack 142 CATCH_ALL implicit-def $arguments 143 CLEANUPRET implicit-def dead $arguments 144 145 bb.9 (landing-pad): 146 ; predecessors: %bb.2, %bb.6, %bb.8 147 liveins: $value_stack 148 CATCH_ALL implicit-def $arguments 149 CLEANUPRET implicit-def dead $arguments 150 151 bb.10: 152 ; predecessors: %bb.6 153 liveins: $value_stack 154 UNREACHABLE implicit-def $arguments 155 )MIR"; 156 157 LLVMContext Context; 158 std::unique_ptr<MIRParser> MIR; 159 MachineModuleInfo MMI(TM.get()); 160 std::unique_ptr<Module> M = 161 parseMIR(Context, MIR, *TM, MIRString, "test0", MMI); 162 ASSERT_TRUE(M); 163 164 Function *F = M->getFunction("test0"); 165 auto *MF = MMI.getMachineFunction(*F); 166 ASSERT_TRUE(MF); 167 168 WebAssemblyExceptionInfo WEI; 169 MachineDominatorTree MDT; 170 MachineDominanceFrontier MDF; 171 MDT.runOnMachineFunction(*MF); 172 MDF.getBase().analyze(MDT.getBase()); 173 WEI.recalculate(MDT, MDF); 174 175 // Exception info structure: 176 // |- bb2 (ehpad), bb3, bb4, bb5, bb6, bb8, bb9, bb10 177 // |- bb3 (ehpad), bb4, bb5, bb6, bb8, bb10 178 // |- bb8 (ehpad) 179 // |- bb9 (ehpad) 180 181 auto *MBB2 = MF->getBlockNumbered(2); 182 auto *WE0 = WEI.getExceptionFor(MBB2); 183 ASSERT_TRUE(WE0); 184 EXPECT_EQ(WE0->getEHPad(), MBB2); 185 EXPECT_EQ(WE0->getParentException(), nullptr); 186 EXPECT_EQ(WE0->getExceptionDepth(), (unsigned)1); 187 188 auto *MBB3 = MF->getBlockNumbered(3); 189 auto *WE0_0 = WEI.getExceptionFor(MBB3); 190 ASSERT_TRUE(WE0_0); 191 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 192 EXPECT_EQ(WE0_0->getParentException(), WE0); 193 EXPECT_EQ(WE0_0->getExceptionDepth(), (unsigned)2); 194 195 auto *MBB4 = MF->getBlockNumbered(4); 196 WE0_0 = WEI.getExceptionFor(MBB4); 197 ASSERT_TRUE(WE0_0); 198 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 199 200 auto *MBB5 = MF->getBlockNumbered(5); 201 WE0_0 = WEI.getExceptionFor(MBB5); 202 ASSERT_TRUE(WE0_0); 203 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 204 205 auto *MBB6 = MF->getBlockNumbered(6); 206 WE0_0 = WEI.getExceptionFor(MBB6); 207 ASSERT_TRUE(WE0_0); 208 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 209 210 auto *MBB10 = MF->getBlockNumbered(10); 211 WE0_0 = WEI.getExceptionFor(MBB10); 212 ASSERT_TRUE(WE0_0); 213 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 214 215 auto *MBB8 = MF->getBlockNumbered(8); 216 auto *WE0_0_0 = WEI.getExceptionFor(MBB8); 217 ASSERT_TRUE(WE0_0_0); 218 EXPECT_EQ(WE0_0_0->getEHPad(), MBB8); 219 EXPECT_EQ(WE0_0_0->getParentException(), WE0_0); 220 EXPECT_EQ(WE0_0_0->getExceptionDepth(), (unsigned)3); 221 222 auto *MBB9 = MF->getBlockNumbered(9); 223 auto *WE0_1 = WEI.getExceptionFor(MBB9); 224 ASSERT_TRUE(WE0_1); 225 EXPECT_EQ(WE0_1->getEHPad(), MBB9); 226 EXPECT_EQ(WE0_1->getParentException(), WE0); 227 EXPECT_EQ(WE0_1->getExceptionDepth(), (unsigned)2); 228 } 229 230 TEST(WebAssemblyExceptionInfoTest, TEST1) { 231 std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine(); 232 ASSERT_TRUE(TM); 233 234 StringRef MIRString = R"MIR( 235 --- | 236 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" 237 target triple = "wasm32-unknown-unknown" 238 239 declare i32 @__gxx_wasm_personality_v0(...) 240 241 define hidden void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { 242 unreachable 243 } 244 245 ... 246 --- 247 name: test1 248 liveins: 249 - { reg: '$arguments' } 250 - { reg: '$value_stack' } 251 body: | 252 bb.0: 253 successors: %bb.9, %bb.1 254 liveins: $arguments, $value_stack 255 BR %bb.9, implicit-def dead $arguments 256 257 bb.1 (landing-pad): 258 ; predecessors: %bb.0 259 successors: %bb.2, %bb.8 260 liveins: $value_stack 261 %52:i32 = CATCH_I32 0, implicit-def dead $arguments 262 BR_IF %bb.2, %32:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack 263 BR %bb.8, implicit-def $arguments 264 265 bb.2: 266 ; predecessors: %bb.1 267 successors: %bb.7, %bb.3, %bb.11 268 liveins: $value_stack 269 BR %bb.7, implicit-def dead $arguments 270 271 bb.3 (landing-pad): 272 ; predecessors: %bb.2 273 successors: %bb.4, %bb.6 274 liveins: $value_stack 275 CATCH_ALL implicit-def $arguments 276 BR_IF %bb.4, %43:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack 277 BR %bb.6, implicit-def $arguments 278 279 bb.4: 280 ; predecessors: %bb.3 281 successors: %bb.5, %bb.10 282 liveins: $value_stack 283 BR %bb.5, implicit-def dead $arguments 284 285 bb.5: 286 ; predecessors: %bb.4 287 successors: %bb.7(0x80000000); %bb.7(200.00%) 288 liveins: $value_stack 289 CATCHRET %bb.7, %bb.1, implicit-def dead $arguments 290 291 bb.6: 292 ; predecessors: %bb.3 293 successors: %bb.12, %bb.11 294 liveins: $value_stack 295 BR %bb.12, implicit-def dead $arguments 296 297 bb.7: 298 ; predecessors: %bb.2, %bb.5 299 successors: %bb.9(0x80000000); %bb.9(200.00%) 300 liveins: $value_stack 301 CATCHRET %bb.9, %bb.0, implicit-def dead $arguments 302 303 bb.8: 304 ; predecessors: %bb.1 305 liveins: $value_stack 306 UNREACHABLE implicit-def $arguments 307 308 bb.9: 309 ; predecessors: %bb.0, %bb.7 310 liveins: $value_stack 311 RETURN_VOID implicit-def $arguments 312 313 bb.10 (landing-pad): 314 ; predecessors: %bb.4 315 successors: %bb.11 316 liveins: $value_stack 317 CATCH_ALL implicit-def $arguments 318 CLEANUPRET implicit-def dead $arguments 319 320 bb.11 (landing-pad): 321 ; predecessors: %bb.2, %bb.6, %bb.10 322 liveins: $value_stack 323 CATCH_ALL implicit-def $arguments 324 CLEANUPRET implicit-def dead $arguments 325 326 bb.12: 327 ; predecessors: %bb.6 328 liveins: $value_stack 329 UNREACHABLE implicit-def $arguments 330 )MIR"; 331 332 LLVMContext Context; 333 std::unique_ptr<MIRParser> MIR; 334 MachineModuleInfo MMI(TM.get()); 335 std::unique_ptr<Module> M = 336 parseMIR(Context, MIR, *TM, MIRString, "test1", MMI); 337 ASSERT_TRUE(M); 338 339 Function *F = M->getFunction("test1"); 340 auto *MF = MMI.getMachineFunction(*F); 341 ASSERT_TRUE(MF); 342 343 WebAssemblyExceptionInfo WEI; 344 MachineDominatorTree MDT; 345 MachineDominanceFrontier MDF; 346 MDT.runOnMachineFunction(*MF); 347 MDF.getBase().analyze(MDT.getBase()); 348 WEI.recalculate(MDT, MDF); 349 350 // Exception info structure: 351 // |- bb1 (ehpad), bb2, bb3, bb4, bb5, bb6, bb7, bb8, bb10, bb11, bb12 352 // |- bb3 (ehpad), bb4, bb5, bb6, bb10, bb12 353 // |- bb10 (ehpad) 354 // |- bb11 (ehpad) 355 356 auto *MBB1 = MF->getBlockNumbered(1); 357 auto *WE0 = WEI.getExceptionFor(MBB1); 358 ASSERT_TRUE(WE0); 359 EXPECT_EQ(WE0->getEHPad(), MBB1); 360 EXPECT_EQ(WE0->getParentException(), nullptr); 361 EXPECT_EQ(WE0->getExceptionDepth(), (unsigned)1); 362 363 auto *MBB2 = MF->getBlockNumbered(2); 364 WE0 = WEI.getExceptionFor(MBB2); 365 ASSERT_TRUE(WE0); 366 EXPECT_EQ(WE0->getEHPad(), MBB1); 367 368 auto *MBB7 = MF->getBlockNumbered(7); 369 WE0 = WEI.getExceptionFor(MBB7); 370 ASSERT_TRUE(WE0); 371 EXPECT_EQ(WE0->getEHPad(), MBB1); 372 373 auto *MBB8 = MF->getBlockNumbered(8); 374 WE0 = WEI.getExceptionFor(MBB8); 375 ASSERT_TRUE(WE0); 376 EXPECT_EQ(WE0->getEHPad(), MBB1); 377 378 auto *MBB3 = MF->getBlockNumbered(3); 379 auto *WE0_0 = WEI.getExceptionFor(MBB3); 380 ASSERT_TRUE(WE0_0); 381 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 382 EXPECT_EQ(WE0_0->getParentException(), WE0); 383 EXPECT_EQ(WE0_0->getExceptionDepth(), (unsigned)2); 384 385 auto *MBB4 = MF->getBlockNumbered(4); 386 WE0_0 = WEI.getExceptionFor(MBB4); 387 ASSERT_TRUE(WE0_0); 388 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 389 390 auto *MBB5 = MF->getBlockNumbered(5); 391 WE0_0 = WEI.getExceptionFor(MBB5); 392 ASSERT_TRUE(WE0_0); 393 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 394 395 auto *MBB6 = MF->getBlockNumbered(6); 396 WE0_0 = WEI.getExceptionFor(MBB6); 397 ASSERT_TRUE(WE0_0); 398 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 399 400 auto *MBB12 = MF->getBlockNumbered(12); 401 WE0_0 = WEI.getExceptionFor(MBB12); 402 ASSERT_TRUE(WE0_0); 403 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 404 405 auto *MBB10 = MF->getBlockNumbered(10); 406 auto *WE0_0_0 = WEI.getExceptionFor(MBB10); 407 ASSERT_TRUE(WE0_0_0); 408 EXPECT_EQ(WE0_0_0->getEHPad(), MBB10); 409 EXPECT_EQ(WE0_0_0->getParentException(), WE0_0); 410 EXPECT_EQ(WE0_0_0->getExceptionDepth(), (unsigned)3); 411 412 auto *MBB11 = MF->getBlockNumbered(11); 413 auto *WE0_1 = WEI.getExceptionFor(MBB11); 414 ASSERT_TRUE(WE0_1); 415 EXPECT_EQ(WE0_1->getEHPad(), MBB11); 416 EXPECT_EQ(WE0_1->getParentException(), WE0); 417 EXPECT_EQ(WE0_1->getExceptionDepth(), (unsigned)2); 418 } 419 420 // Terminate pad test 421 TEST(WebAssemblyExceptionInfoTest, TEST2) { 422 std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine(); 423 ASSERT_TRUE(TM); 424 425 StringRef MIRString = R"MIR( 426 --- | 427 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" 428 target triple = "wasm32-unknown-unknown" 429 430 declare i32 @__gxx_wasm_personality_v0(...) 431 declare void @_ZSt9terminatev() 432 declare void @__clang_call_terminate(i8*) 433 434 define hidden void @test2() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { 435 unreachable 436 } 437 438 ... 439 --- 440 name: test2 441 liveins: 442 - { reg: '$arguments' } 443 - { reg: '$value_stack' } 444 body: | 445 bb.0: 446 successors: %bb.3, %bb.1 447 BR %bb.3, implicit-def dead $arguments 448 449 bb.1 (landing-pad): 450 ; predecessors: %bb.0 451 successors: %bb.2, %bb.4 452 %3:i32 = CATCH_I32 0, implicit-def dead $arguments 453 BR %bb.2, implicit-def dead $arguments 454 455 bb.2: 456 ; predecessors: %bb.1 457 successors: %bb.3(0x80000000); %bb.3(200.00%) 458 CATCHRET %bb.3, %bb.0, implicit-def dead $arguments 459 460 bb.3: 461 ; predecessors: %bb.0, %bb.2 462 RETURN_VOID implicit-def $arguments 463 464 bb.4 (landing-pad): 465 ; predecessors: %bb.1 466 successors: %bb.5, %bb.6 467 CATCH_ALL implicit-def $arguments 468 BR %bb.5, implicit-def dead $arguments 469 470 bb.5: 471 ; predecessors: %bb.4 472 CLEANUPRET implicit-def dead $arguments 473 474 bb.6 (landing-pad): 475 ; predecessors: %bb.4 476 successors: %bb.7(0x80000000); %bb.7(200.00%) 477 %6:i32 = CATCH_I32 0, implicit-def dead $arguments 478 CALL_VOID @__clang_call_terminate, %7:i32, implicit-def $arguments 479 UNREACHABLE implicit-def $arguments 480 481 bb.7 (landing-pad): 482 ; predecessors: %bb.6 483 CATCH_ALL implicit-def $arguments 484 CALL_VOID @_ZSt9terminatev, implicit-def $arguments 485 UNREACHABLE implicit-def $arguments 486 )MIR"; 487 488 LLVMContext Context; 489 std::unique_ptr<MIRParser> MIR; 490 MachineModuleInfo MMI(TM.get()); 491 std::unique_ptr<Module> M = 492 parseMIR(Context, MIR, *TM, MIRString, "test2", MMI); 493 ASSERT_TRUE(M); 494 495 Function *F = M->getFunction("test2"); 496 auto *MF = MMI.getMachineFunction(*F); 497 ASSERT_TRUE(MF); 498 499 WebAssemblyExceptionInfo WEI; 500 MachineDominatorTree MDT; 501 MachineDominanceFrontier MDF; 502 MDT.runOnMachineFunction(*MF); 503 MDF.getBase().analyze(MDT.getBase()); 504 WEI.recalculate(MDT, MDF); 505 506 // Exception info structure: 507 // |- bb1 (ehpad), bb2, bb4, bb5, bb6, bb7 508 // |- bb4 (ehpad), bb5, bb6, bb7 509 // |- bb6 (ehpad), bb7 510 // 511 // Here, bb6 is a terminate pad with a 'catch' instruction, and bb7 is a 512 // terminate pad with a 'catch_all' instruction, In this case we put bb6 and 513 // bb7 into one exception. 514 515 auto *MBB1 = MF->getBlockNumbered(1); 516 auto *WE0 = WEI.getExceptionFor(MBB1); 517 ASSERT_TRUE(WE0); 518 EXPECT_EQ(WE0->getEHPad(), MBB1); 519 EXPECT_EQ(WE0->getParentException(), nullptr); 520 EXPECT_EQ(WE0->getExceptionDepth(), (unsigned)1); 521 522 auto *MBB2 = MF->getBlockNumbered(2); 523 WE0 = WEI.getExceptionFor(MBB2); 524 ASSERT_TRUE(WE0); 525 EXPECT_EQ(WE0->getEHPad(), MBB1); 526 527 auto *MBB4 = MF->getBlockNumbered(4); 528 auto *WE0_0 = WEI.getExceptionFor(MBB4); 529 ASSERT_TRUE(WE0_0); 530 EXPECT_EQ(WE0_0->getEHPad(), MBB4); 531 EXPECT_EQ(WE0_0->getParentException(), WE0); 532 EXPECT_EQ(WE0_0->getExceptionDepth(), (unsigned)2); 533 534 auto *MBB5 = MF->getBlockNumbered(5); 535 WE0_0 = WEI.getExceptionFor(MBB5); 536 ASSERT_TRUE(WE0_0); 537 EXPECT_EQ(WE0_0->getEHPad(), MBB4); 538 539 auto *MBB6 = MF->getBlockNumbered(6); 540 auto *WE0_0_0 = WEI.getExceptionFor(MBB6); 541 ASSERT_TRUE(WE0_0_0); 542 EXPECT_EQ(WE0_0_0->getEHPad(), MBB6); 543 EXPECT_EQ(WE0_0_0->getParentException(), WE0_0); 544 EXPECT_EQ(WE0_0_0->getExceptionDepth(), (unsigned)3); 545 546 auto *MBB7 = MF->getBlockNumbered(7); 547 WE0_0_0 = WEI.getExceptionFor(MBB7); 548 ASSERT_TRUE(WE0_0_0); 549 EXPECT_EQ(WE0_0_0->getEHPad(), MBB6); 550 } 551