1 //=== WebAssemblyExceptionInfoTest.cpp - WebAssemblyExceptionInfo unit tests =// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "WebAssemblyExceptionInfo.h" 10 #include "llvm/CodeGen/MIRParser/MIRParser.h" 11 #include "llvm/CodeGen/MachineDominanceFrontier.h" 12 #include "llvm/CodeGen/MachineDominators.h" 13 #include "llvm/CodeGen/MachineModuleInfo.h" 14 #include "llvm/Support/SourceMgr.h" 15 #include "llvm/Support/TargetRegistry.h" 16 #include "llvm/Support/TargetSelect.h" 17 #include "llvm/Target/TargetMachine.h" 18 #include "gtest/gtest.h" 19 20 using namespace llvm; 21 22 namespace { 23 24 std::unique_ptr<LLVMTargetMachine> createTargetMachine() { 25 auto TT(Triple::normalize("wasm32-unknown-unknown")); 26 std::string CPU(""); 27 std::string FS(""); 28 29 LLVMInitializeWebAssemblyTargetInfo(); 30 LLVMInitializeWebAssemblyTarget(); 31 LLVMInitializeWebAssemblyTargetMC(); 32 33 std::string Error; 34 const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error); 35 assert(TheTarget); 36 37 return std::unique_ptr<LLVMTargetMachine>(static_cast<LLVMTargetMachine*>( 38 TheTarget->createTargetMachine(TT, CPU, FS, TargetOptions(), None, None, 39 CodeGenOpt::Default))); 40 } 41 42 std::unique_ptr<Module> parseMIR(LLVMContext &Context, 43 std::unique_ptr<MIRParser> &MIR, 44 const TargetMachine &TM, StringRef MIRCode, 45 const char *FuncName, MachineModuleInfo &MMI) { 46 SMDiagnostic Diagnostic; 47 std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRCode); 48 MIR = createMIRParser(std::move(MBuffer), Context); 49 if (!MIR) 50 return nullptr; 51 52 std::unique_ptr<Module> M = MIR->parseIRModule(); 53 if (!M) 54 return nullptr; 55 56 M->setDataLayout(TM.createDataLayout()); 57 58 if (MIR->parseMachineFunctions(*M, MMI)) 59 return nullptr; 60 61 return M; 62 } 63 64 } // namespace 65 66 TEST(WebAssemblyExceptionInfoTest, TEST0) { 67 std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine(); 68 ASSERT_TRUE(TM); 69 70 StringRef MIRString = R"MIR( 71 --- | 72 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" 73 target triple = "wasm32-unknown-unknown" 74 75 declare i32 @__gxx_wasm_personality_v0(...) 76 77 define void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { 78 unreachable 79 } 80 81 ... 82 --- 83 name: test0 84 liveins: 85 - { reg: '$arguments' } 86 - { reg: '$value_stack' } 87 body: | 88 bb.0: 89 successors: %bb.1, %bb.2 90 liveins: $arguments, $value_stack 91 BR %bb.1, implicit-def dead $arguments 92 93 bb.1: 94 ; predecessors: %bb.0 95 successors: %bb.7 96 liveins: $value_stack 97 BR %bb.7, implicit-def $arguments 98 99 bb.2 (landing-pad): 100 ; predecessors: %bb.0 101 successors: %bb.3, %bb.9 102 liveins: $value_stack 103 CATCH_ALL implicit-def $arguments 104 RETHROW 0, implicit-def dead $arguments 105 106 bb.3 (landing-pad): 107 ; predecessors: %bb.2 108 successors: %bb.4, %bb.6 109 liveins: $value_stack 110 %1:i32 = CATCH &__cpp_exception, implicit-def $arguments 111 BR_IF %bb.4, %58:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack 112 BR %bb.6, implicit-def $arguments 113 114 bb.4: 115 ; predecessors: %bb.3 116 successors: %bb.5, %bb.8 117 liveins: $value_stack 118 BR %bb.5, implicit-def dead $arguments 119 120 bb.5: 121 ; predecessors: %bb.4 122 successors: %bb.7 123 liveins: $value_stack 124 BR %bb.7, implicit-def dead $arguments 125 126 bb.6: 127 ; predecessors: %bb.3 128 successors: %bb.10, %bb.9 129 liveins: $value_stack 130 BR %bb.10, implicit-def dead $arguments 131 132 bb.7: 133 ; predecessors: %bb.5, %bb.1 134 liveins: $value_stack 135 RETURN implicit-def $arguments 136 137 bb.8 (landing-pad): 138 ; predecessors: %bb.4 139 successors: %bb.9 140 liveins: $value_stack 141 CATCH_ALL implicit-def $arguments 142 RETHROW 0, implicit-def dead $arguments 143 144 bb.9 (landing-pad): 145 ; predecessors: %bb.2, %bb.6, %bb.8 146 liveins: $value_stack 147 CATCH_ALL implicit-def $arguments 148 RETHROW 0, implicit-def dead $arguments 149 150 bb.10: 151 ; predecessors: %bb.6 152 liveins: $value_stack 153 UNREACHABLE implicit-def $arguments 154 )MIR"; 155 156 LLVMContext Context; 157 std::unique_ptr<MIRParser> MIR; 158 MachineModuleInfo MMI(TM.get()); 159 std::unique_ptr<Module> M = 160 parseMIR(Context, MIR, *TM, MIRString, "test0", MMI); 161 ASSERT_TRUE(M); 162 163 Function *F = M->getFunction("test0"); 164 auto *MF = MMI.getMachineFunction(*F); 165 ASSERT_TRUE(MF); 166 167 WebAssemblyExceptionInfo WEI; 168 MachineDominatorTree MDT; 169 MachineDominanceFrontier MDF; 170 MDT.runOnMachineFunction(*MF); 171 MDF.getBase().analyze(MDT.getBase()); 172 WEI.recalculate(*MF, MDT, MDF); 173 174 // Exception info structure: 175 // |- bb2 (ehpad), bb3, bb4, bb5, bb6, bb8, bb9, bb10 176 // |- bb3 (ehpad), bb4, bb5, bb6, bb8, bb10 177 // |- bb8 (ehpad) 178 // |- bb9 (ehpad) 179 180 auto *MBB2 = MF->getBlockNumbered(2); 181 auto *WE0 = WEI.getExceptionFor(MBB2); 182 ASSERT_TRUE(WE0); 183 EXPECT_EQ(WE0->getEHPad(), MBB2); 184 EXPECT_EQ(WE0->getParentException(), nullptr); 185 EXPECT_EQ(WE0->getExceptionDepth(), (unsigned)1); 186 187 auto *MBB3 = MF->getBlockNumbered(3); 188 auto *WE0_0 = WEI.getExceptionFor(MBB3); 189 ASSERT_TRUE(WE0_0); 190 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 191 EXPECT_EQ(WE0_0->getParentException(), WE0); 192 EXPECT_EQ(WE0_0->getExceptionDepth(), (unsigned)2); 193 194 auto *MBB4 = MF->getBlockNumbered(4); 195 WE0_0 = WEI.getExceptionFor(MBB4); 196 ASSERT_TRUE(WE0_0); 197 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 198 199 auto *MBB5 = MF->getBlockNumbered(5); 200 WE0_0 = WEI.getExceptionFor(MBB5); 201 ASSERT_TRUE(WE0_0); 202 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 203 204 auto *MBB6 = MF->getBlockNumbered(6); 205 WE0_0 = WEI.getExceptionFor(MBB6); 206 ASSERT_TRUE(WE0_0); 207 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 208 209 auto *MBB10 = MF->getBlockNumbered(10); 210 WE0_0 = WEI.getExceptionFor(MBB10); 211 ASSERT_TRUE(WE0_0); 212 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 213 214 auto *MBB8 = MF->getBlockNumbered(8); 215 auto *WE0_0_0 = WEI.getExceptionFor(MBB8); 216 ASSERT_TRUE(WE0_0_0); 217 EXPECT_EQ(WE0_0_0->getEHPad(), MBB8); 218 EXPECT_EQ(WE0_0_0->getParentException(), WE0_0); 219 EXPECT_EQ(WE0_0_0->getExceptionDepth(), (unsigned)3); 220 221 auto *MBB9 = MF->getBlockNumbered(9); 222 auto *WE0_1 = WEI.getExceptionFor(MBB9); 223 ASSERT_TRUE(WE0_1); 224 EXPECT_EQ(WE0_1->getEHPad(), MBB9); 225 EXPECT_EQ(WE0_1->getParentException(), WE0); 226 EXPECT_EQ(WE0_1->getExceptionDepth(), (unsigned)2); 227 } 228 229 TEST(WebAssemblyExceptionInfoTest, TEST1) { 230 std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine(); 231 ASSERT_TRUE(TM); 232 233 StringRef MIRString = R"MIR( 234 --- | 235 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" 236 target triple = "wasm32-unknown-unknown" 237 238 declare i32 @__gxx_wasm_personality_v0(...) 239 240 define void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { 241 unreachable 242 } 243 244 ... 245 --- 246 name: test1 247 liveins: 248 - { reg: '$arguments' } 249 - { reg: '$value_stack' } 250 body: | 251 bb.0: 252 successors: %bb.9, %bb.1 253 liveins: $arguments, $value_stack 254 BR %bb.9, implicit-def dead $arguments 255 256 bb.1 (landing-pad): 257 ; predecessors: %bb.0 258 successors: %bb.2, %bb.8 259 liveins: $value_stack 260 %0:i32 = CATCH &__cpp_exception, implicit-def $arguments 261 BR_IF %bb.2, %32:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack 262 BR %bb.8, implicit-def $arguments 263 264 bb.2: 265 ; predecessors: %bb.1 266 successors: %bb.7, %bb.3, %bb.11 267 liveins: $value_stack 268 BR %bb.7, implicit-def dead $arguments 269 270 bb.3 (landing-pad): 271 ; predecessors: %bb.2 272 successors: %bb.4, %bb.6 273 liveins: $value_stack 274 %1:i32 = CATCH &__cpp_exception, implicit-def $arguments 275 BR_IF %bb.4, %43:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack 276 BR %bb.6, implicit-def $arguments 277 278 bb.4: 279 ; predecessors: %bb.3 280 successors: %bb.5, %bb.10 281 liveins: $value_stack 282 BR %bb.5, implicit-def dead $arguments 283 284 bb.5: 285 ; predecessors: %bb.4 286 successors: %bb.7(0x80000000); %bb.7(200.00%) 287 liveins: $value_stack 288 BR %bb.7, implicit-def dead $arguments 289 290 bb.6: 291 ; predecessors: %bb.3 292 successors: %bb.12, %bb.11 293 liveins: $value_stack 294 BR %bb.12, implicit-def dead $arguments 295 296 bb.7: 297 ; predecessors: %bb.2, %bb.5 298 successors: %bb.9(0x80000000); %bb.9(200.00%) 299 liveins: $value_stack 300 BR %bb.9, implicit-def dead $arguments 301 302 bb.8: 303 ; predecessors: %bb.1 304 liveins: $value_stack 305 UNREACHABLE implicit-def $arguments 306 307 bb.9: 308 ; predecessors: %bb.0, %bb.7 309 liveins: $value_stack 310 RETURN implicit-def $arguments 311 312 bb.10 (landing-pad): 313 ; predecessors: %bb.4 314 successors: %bb.11 315 liveins: $value_stack 316 CATCH_ALL implicit-def $arguments 317 RETHROW 0, implicit-def dead $arguments 318 319 bb.11 (landing-pad): 320 ; predecessors: %bb.2, %bb.6, %bb.10 321 liveins: $value_stack 322 CATCH_ALL implicit-def $arguments 323 RETHROW 0, implicit-def dead $arguments 324 325 bb.12: 326 ; predecessors: %bb.6 327 liveins: $value_stack 328 UNREACHABLE implicit-def $arguments 329 )MIR"; 330 331 LLVMContext Context; 332 std::unique_ptr<MIRParser> MIR; 333 MachineModuleInfo MMI(TM.get()); 334 std::unique_ptr<Module> M = 335 parseMIR(Context, MIR, *TM, MIRString, "test1", MMI); 336 ASSERT_TRUE(M); 337 338 Function *F = M->getFunction("test1"); 339 auto *MF = MMI.getMachineFunction(*F); 340 ASSERT_TRUE(MF); 341 342 WebAssemblyExceptionInfo WEI; 343 MachineDominatorTree MDT; 344 MachineDominanceFrontier MDF; 345 MDT.runOnMachineFunction(*MF); 346 MDF.getBase().analyze(MDT.getBase()); 347 WEI.recalculate(*MF, MDT, MDF); 348 349 // Exception info structure: 350 // |- bb1 (ehpad), bb2, bb3, bb4, bb5, bb6, bb7, bb8, bb10, bb11, bb12 351 // |- bb3 (ehpad), bb4, bb5, bb6, bb10, bb12 352 // |- bb10 (ehpad) 353 // |- bb11 (ehpad) 354 355 auto *MBB1 = MF->getBlockNumbered(1); 356 auto *WE0 = WEI.getExceptionFor(MBB1); 357 ASSERT_TRUE(WE0); 358 EXPECT_EQ(WE0->getEHPad(), MBB1); 359 EXPECT_EQ(WE0->getParentException(), nullptr); 360 EXPECT_EQ(WE0->getExceptionDepth(), (unsigned)1); 361 362 auto *MBB2 = MF->getBlockNumbered(2); 363 WE0 = WEI.getExceptionFor(MBB2); 364 ASSERT_TRUE(WE0); 365 EXPECT_EQ(WE0->getEHPad(), MBB1); 366 367 auto *MBB7 = MF->getBlockNumbered(7); 368 WE0 = WEI.getExceptionFor(MBB7); 369 ASSERT_TRUE(WE0); 370 EXPECT_EQ(WE0->getEHPad(), MBB1); 371 372 auto *MBB8 = MF->getBlockNumbered(8); 373 WE0 = WEI.getExceptionFor(MBB8); 374 ASSERT_TRUE(WE0); 375 EXPECT_EQ(WE0->getEHPad(), MBB1); 376 377 auto *MBB3 = MF->getBlockNumbered(3); 378 auto *WE0_0 = WEI.getExceptionFor(MBB3); 379 ASSERT_TRUE(WE0_0); 380 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 381 EXPECT_EQ(WE0_0->getParentException(), WE0); 382 EXPECT_EQ(WE0_0->getExceptionDepth(), (unsigned)2); 383 384 auto *MBB4 = MF->getBlockNumbered(4); 385 WE0_0 = WEI.getExceptionFor(MBB4); 386 ASSERT_TRUE(WE0_0); 387 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 388 389 auto *MBB5 = MF->getBlockNumbered(5); 390 WE0_0 = WEI.getExceptionFor(MBB5); 391 ASSERT_TRUE(WE0_0); 392 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 393 394 auto *MBB6 = MF->getBlockNumbered(6); 395 WE0_0 = WEI.getExceptionFor(MBB6); 396 ASSERT_TRUE(WE0_0); 397 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 398 399 auto *MBB12 = MF->getBlockNumbered(12); 400 WE0_0 = WEI.getExceptionFor(MBB12); 401 ASSERT_TRUE(WE0_0); 402 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 403 404 auto *MBB10 = MF->getBlockNumbered(10); 405 auto *WE0_0_0 = WEI.getExceptionFor(MBB10); 406 ASSERT_TRUE(WE0_0_0); 407 EXPECT_EQ(WE0_0_0->getEHPad(), MBB10); 408 EXPECT_EQ(WE0_0_0->getParentException(), WE0_0); 409 EXPECT_EQ(WE0_0_0->getExceptionDepth(), (unsigned)3); 410 411 auto *MBB11 = MF->getBlockNumbered(11); 412 auto *WE0_1 = WEI.getExceptionFor(MBB11); 413 ASSERT_TRUE(WE0_1); 414 EXPECT_EQ(WE0_1->getEHPad(), MBB11); 415 EXPECT_EQ(WE0_1->getParentException(), WE0); 416 EXPECT_EQ(WE0_1->getExceptionDepth(), (unsigned)2); 417 } 418