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<TargetMachine> 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<TargetMachine>( 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 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<TargetMachine> 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_LEGACY 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_LEGACY &__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_LEGACY 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_LEGACY 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 = parseMIR(Context, MIR, *TM, MIRString, 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.recalculate(*MF); 171 MDF.getBase().analyze(MDT); 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<TargetMachine> 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_LEGACY &__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_LEGACY &__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_LEGACY 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_LEGACY 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 = parseMIR(Context, MIR, *TM, MIRString, MMI); 335 ASSERT_TRUE(M); 336 337 Function *F = M->getFunction("test1"); 338 auto *MF = MMI.getMachineFunction(*F); 339 ASSERT_TRUE(MF); 340 341 WebAssemblyExceptionInfo WEI; 342 MachineDominatorTree MDT; 343 MachineDominanceFrontier MDF; 344 MDT.recalculate(*MF); 345 MDF.getBase().analyze(MDT); 346 WEI.recalculate(*MF, MDT, MDF); 347 348 // Exception info structure: 349 // |- bb1 (ehpad), bb2, bb3, bb4, bb5, bb6, bb7, bb8, bb10, bb11, bb12 350 // |- bb3 (ehpad), bb4, bb5, bb6, bb10, bb12 351 // |- bb10 (ehpad) 352 // |- bb11 (ehpad) 353 354 auto *MBB1 = MF->getBlockNumbered(1); 355 auto *WE0 = WEI.getExceptionFor(MBB1); 356 ASSERT_TRUE(WE0); 357 EXPECT_EQ(WE0->getEHPad(), MBB1); 358 EXPECT_EQ(WE0->getParentException(), nullptr); 359 EXPECT_EQ(WE0->getExceptionDepth(), (unsigned)1); 360 361 auto *MBB2 = MF->getBlockNumbered(2); 362 WE0 = WEI.getExceptionFor(MBB2); 363 ASSERT_TRUE(WE0); 364 EXPECT_EQ(WE0->getEHPad(), MBB1); 365 366 auto *MBB7 = MF->getBlockNumbered(7); 367 WE0 = WEI.getExceptionFor(MBB7); 368 ASSERT_TRUE(WE0); 369 EXPECT_EQ(WE0->getEHPad(), MBB1); 370 371 auto *MBB8 = MF->getBlockNumbered(8); 372 WE0 = WEI.getExceptionFor(MBB8); 373 ASSERT_TRUE(WE0); 374 EXPECT_EQ(WE0->getEHPad(), MBB1); 375 376 auto *MBB3 = MF->getBlockNumbered(3); 377 auto *WE0_0 = WEI.getExceptionFor(MBB3); 378 ASSERT_TRUE(WE0_0); 379 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 380 EXPECT_EQ(WE0_0->getParentException(), WE0); 381 EXPECT_EQ(WE0_0->getExceptionDepth(), (unsigned)2); 382 383 auto *MBB4 = MF->getBlockNumbered(4); 384 WE0_0 = WEI.getExceptionFor(MBB4); 385 ASSERT_TRUE(WE0_0); 386 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 387 388 auto *MBB5 = MF->getBlockNumbered(5); 389 WE0_0 = WEI.getExceptionFor(MBB5); 390 ASSERT_TRUE(WE0_0); 391 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 392 393 auto *MBB6 = MF->getBlockNumbered(6); 394 WE0_0 = WEI.getExceptionFor(MBB6); 395 ASSERT_TRUE(WE0_0); 396 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 397 398 auto *MBB12 = MF->getBlockNumbered(12); 399 WE0_0 = WEI.getExceptionFor(MBB12); 400 ASSERT_TRUE(WE0_0); 401 EXPECT_EQ(WE0_0->getEHPad(), MBB3); 402 403 auto *MBB10 = MF->getBlockNumbered(10); 404 auto *WE0_0_0 = WEI.getExceptionFor(MBB10); 405 ASSERT_TRUE(WE0_0_0); 406 EXPECT_EQ(WE0_0_0->getEHPad(), MBB10); 407 EXPECT_EQ(WE0_0_0->getParentException(), WE0_0); 408 EXPECT_EQ(WE0_0_0->getExceptionDepth(), (unsigned)3); 409 410 auto *MBB11 = MF->getBlockNumbered(11); 411 auto *WE0_1 = WEI.getExceptionFor(MBB11); 412 ASSERT_TRUE(WE0_1); 413 EXPECT_EQ(WE0_1->getEHPad(), MBB11); 414 EXPECT_EQ(WE0_1->getParentException(), WE0); 415 EXPECT_EQ(WE0_1->getExceptionDepth(), (unsigned)2); 416 } 417