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/IR/Module.h" 15 #include "llvm/MC/TargetRegistry.h" 16 #include "llvm/Support/SourceMgr.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(), std::nullopt, 40 std::nullopt, CodeGenOptLevel::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 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 RETHROW 0, 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 %1:i32 = CATCH &__cpp_exception, 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 BR %bb.7, 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 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 RETHROW 0, 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 RETHROW 0, 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.calculate(*MF); 172 MDF.getBase().analyze(MDT.getBase()); 173 WEI.recalculate(*MF, 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 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 %0:i32 = CATCH &__cpp_exception, implicit-def $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 %1:i32 = CATCH &__cpp_exception, 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 BR %bb.7, 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 BR %bb.9, 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 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 RETHROW 0, 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 RETHROW 0, 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.calculate(*MF); 347 MDF.getBase().analyze(MDT.getBase()); 348 WEI.recalculate(*MF, 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