diff options
author | Heejin Ahn <aheejin@gmail.com> | 2018-06-25 01:20:21 +0000 |
---|---|---|
committer | Heejin Ahn <aheejin@gmail.com> | 2018-06-25 01:20:21 +0000 |
commit | 04c48949116d2e3407f76856476c00417abdb076 (patch) | |
tree | 073ce1dc1343c7fefeb183da238b8b1bd52c2620 /llvm/unittests/Target/WebAssembly/WebAssemblyExceptionInfoTest.cpp | |
parent | 4934f76b58403059e810a4559dcbde27bfab65d4 (diff) | |
download | bcm5719-llvm-04c48949116d2e3407f76856476c00417abdb076.tar.gz bcm5719-llvm-04c48949116d2e3407f76856476c00417abdb076.zip |
[WebAssembly] Add WebAssemblyException information analysis
Summary:
A WebAssemblyException object contains BBs that belong to a 'catch' part
of the try-catch-end structure. Because CFGSort requires all the BBs
within a catch part to be sorted together as it does for loops, this
pass calculates the nesting structure of catch part of exceptions in a
function. Now this assumes the use of Windows EH instructions.
Reviewers: dschuff, majnemer
Subscribers: jfb, mgorny, sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D44134
llvm-svn: 335439
Diffstat (limited to 'llvm/unittests/Target/WebAssembly/WebAssemblyExceptionInfoTest.cpp')
-rw-r--r-- | llvm/unittests/Target/WebAssembly/WebAssemblyExceptionInfoTest.cpp | 549 |
1 files changed, 549 insertions, 0 deletions
diff --git a/llvm/unittests/Target/WebAssembly/WebAssemblyExceptionInfoTest.cpp b/llvm/unittests/Target/WebAssembly/WebAssemblyExceptionInfoTest.cpp new file mode 100644 index 00000000000..599f2e7f10f --- /dev/null +++ b/llvm/unittests/Target/WebAssembly/WebAssemblyExceptionInfoTest.cpp @@ -0,0 +1,549 @@ +//=== WebAssemblyExceptionInfoTest.cpp - WebAssebmlyExceptionInfo unit tests =// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "WebAssemblyExceptionInfo.h" +#include "llvm/CodeGen/MIRParser/MIRParser.h" +#include "llvm/CodeGen/MachineDominanceFrontier.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Target/TargetMachine.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +std::unique_ptr<TargetMachine> createTargetMachine() { + auto TT(Triple::normalize("wasm32-unknown-unknown")); + std::string CPU(""); + std::string FS(""); + + LLVMInitializeWebAssemblyTargetInfo(); + LLVMInitializeWebAssemblyTarget(); + LLVMInitializeWebAssemblyTargetMC(); + + std::string Error; + const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error); + assert(TheTarget); + + return std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine( + TT, CPU, FS, TargetOptions(), None, None, CodeGenOpt::Default)); +} + +std::unique_ptr<Module> parseMIR(LLVMContext &Context, + std::unique_ptr<MIRParser> &MIR, + const TargetMachine &TM, StringRef MIRCode, + const char *FuncName, MachineModuleInfo &MMI) { + SMDiagnostic Diagnostic; + std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRCode); + MIR = createMIRParser(std::move(MBuffer), Context); + if (!MIR) + return nullptr; + + std::unique_ptr<Module> M = MIR->parseIRModule(); + if (!M) + return nullptr; + + M->setDataLayout(TM.createDataLayout()); + + if (MIR->parseMachineFunctions(*M, MMI)) + return nullptr; + + return M; +} + +} // namespace + +TEST(WebAssemblyExceptionInfoTest, TEST0) { + std::unique_ptr<TargetMachine> TM = createTargetMachine(); + ASSERT_TRUE(TM); + + StringRef MIRString = R"MIR( +--- | + target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" + target triple = "wasm32-unknown-unknown" + + declare i32 @__gxx_wasm_personality_v0(...) + + define hidden void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { + unreachable + } + +... +--- +name: test0 +liveins: + - { reg: '$arguments' } + - { reg: '$value_stack' } +body: | + bb.0: + successors: %bb.1, %bb.2 + liveins: $arguments, $value_stack + BR %bb.1, implicit-def dead $arguments + + bb.1: + ; predecessors: %bb.0 + successors: %bb.7 + liveins: $value_stack + BR %bb.7, implicit-def $arguments + + bb.2 (landing-pad): + ; predecessors: %bb.0 + successors: %bb.3, %bb.9 + liveins: $value_stack + CATCH_ALL implicit-def $arguments + CLEANUPRET implicit-def dead $arguments + + bb.3 (landing-pad): + ; predecessors: %bb.2 + successors: %bb.4, %bb.6 + liveins: $value_stack + CATCH_ALL implicit-def $arguments + BR_IF %bb.4, %58:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack + BR %bb.6, implicit-def $arguments + + bb.4: + ; predecessors: %bb.3 + successors: %bb.5, %bb.8 + liveins: $value_stack + BR %bb.5, implicit-def dead $arguments + + bb.5: + ; predecessors: %bb.4 + successors: %bb.7 + liveins: $value_stack + CATCHRET %bb.7, %bb.0, implicit-def dead $arguments + + bb.6: + ; predecessors: %bb.3 + successors: %bb.10, %bb.9 + liveins: $value_stack + BR %bb.10, implicit-def dead $arguments + + bb.7: + ; predecessors: %bb.5, %bb.1 + liveins: $value_stack + RETURN_VOID implicit-def $arguments + + bb.8 (landing-pad): + ; predecessors: %bb.4 + successors: %bb.9 + liveins: $value_stack + CATCH_ALL implicit-def $arguments + CLEANUPRET implicit-def dead $arguments + + bb.9 (landing-pad): + ; predecessors: %bb.2, %bb.6, %bb.8 + liveins: $value_stack + CATCH_ALL implicit-def $arguments + CLEANUPRET implicit-def dead $arguments + + bb.10: + ; predecessors: %bb.6 + liveins: $value_stack + UNREACHABLE implicit-def $arguments +)MIR"; + + LLVMContext Context; + std::unique_ptr<MIRParser> MIR; + MachineModuleInfo MMI(TM.get()); + std::unique_ptr<Module> M = + parseMIR(Context, MIR, *TM, MIRString, "test0", MMI); + ASSERT_TRUE(M); + + Function *F = M->getFunction("test0"); + auto *MF = MMI.getMachineFunction(*F); + ASSERT_TRUE(MF); + + WebAssemblyExceptionInfo WEI; + MachineDominatorTree MDT; + MachineDominanceFrontier MDF; + MDT.runOnMachineFunction(*MF); + MDF.getBase().analyze(MDT.getBase()); + WEI.recalculate(MDT, MDF); + + // Exception info structure: + // |- bb2 (ehpad), bb3, bb4, bb5, bb6, bb8, bb9, bb10 + // |- bb3 (ehpad), bb4, bb5, bb6, bb8, bb10 + // |- bb8 (ehpad) + // |- bb9 (ehpad) + + auto *MBB2 = MF->getBlockNumbered(2); + auto *WE0 = WEI.getExceptionFor(MBB2); + ASSERT_TRUE(WE0); + EXPECT_EQ(WE0->getEHPad(), MBB2); + EXPECT_EQ(WE0->getParentException(), nullptr); + EXPECT_EQ(WE0->getExceptionDepth(), (unsigned)1); + + auto *MBB3 = MF->getBlockNumbered(3); + auto *WE0_0 = WEI.getExceptionFor(MBB3); + ASSERT_TRUE(WE0_0); + EXPECT_EQ(WE0_0->getEHPad(), MBB3); + EXPECT_EQ(WE0_0->getParentException(), WE0); + EXPECT_EQ(WE0_0->getExceptionDepth(), (unsigned)2); + + auto *MBB4 = MF->getBlockNumbered(4); + WE0_0 = WEI.getExceptionFor(MBB4); + ASSERT_TRUE(WE0_0); + EXPECT_EQ(WE0_0->getEHPad(), MBB3); + + auto *MBB5 = MF->getBlockNumbered(5); + WE0_0 = WEI.getExceptionFor(MBB5); + ASSERT_TRUE(WE0_0); + EXPECT_EQ(WE0_0->getEHPad(), MBB3); + + auto *MBB6 = MF->getBlockNumbered(6); + WE0_0 = WEI.getExceptionFor(MBB6); + ASSERT_TRUE(WE0_0); + EXPECT_EQ(WE0_0->getEHPad(), MBB3); + + auto *MBB10 = MF->getBlockNumbered(10); + WE0_0 = WEI.getExceptionFor(MBB10); + ASSERT_TRUE(WE0_0); + EXPECT_EQ(WE0_0->getEHPad(), MBB3); + + auto *MBB8 = MF->getBlockNumbered(8); + auto *WE0_0_0 = WEI.getExceptionFor(MBB8); + ASSERT_TRUE(WE0_0_0); + EXPECT_EQ(WE0_0_0->getEHPad(), MBB8); + EXPECT_EQ(WE0_0_0->getParentException(), WE0_0); + EXPECT_EQ(WE0_0_0->getExceptionDepth(), (unsigned)3); + + auto *MBB9 = MF->getBlockNumbered(9); + auto *WE0_1 = WEI.getExceptionFor(MBB9); + ASSERT_TRUE(WE0_1); + EXPECT_EQ(WE0_1->getEHPad(), MBB9); + EXPECT_EQ(WE0_1->getParentException(), WE0); + EXPECT_EQ(WE0_1->getExceptionDepth(), (unsigned)2); +} + +TEST(WebAssemblyExceptionInfoTest, TEST1) { + std::unique_ptr<TargetMachine> TM = createTargetMachine(); + ASSERT_TRUE(TM); + + StringRef MIRString = R"MIR( +--- | + target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" + target triple = "wasm32-unknown-unknown" + + declare i32 @__gxx_wasm_personality_v0(...) + + define hidden void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { + unreachable + } + +... +--- +name: test1 +liveins: + - { reg: '$arguments' } + - { reg: '$value_stack' } +body: | + bb.0: + successors: %bb.9, %bb.1 + liveins: $arguments, $value_stack + BR %bb.9, implicit-def dead $arguments + + bb.1 (landing-pad): + ; predecessors: %bb.0 + successors: %bb.2, %bb.8 + liveins: $value_stack + %52:i32 = CATCH_I32 0, implicit-def dead $arguments + BR_IF %bb.2, %32:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack + BR %bb.8, implicit-def $arguments + + bb.2: + ; predecessors: %bb.1 + successors: %bb.7, %bb.3, %bb.11 + liveins: $value_stack + BR %bb.7, implicit-def dead $arguments + + bb.3 (landing-pad): + ; predecessors: %bb.2 + successors: %bb.4, %bb.6 + liveins: $value_stack + CATCH_ALL implicit-def $arguments + BR_IF %bb.4, %43:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack + BR %bb.6, implicit-def $arguments + + bb.4: + ; predecessors: %bb.3 + successors: %bb.5, %bb.10 + liveins: $value_stack + BR %bb.5, implicit-def dead $arguments + + bb.5: + ; predecessors: %bb.4 + successors: %bb.7(0x80000000); %bb.7(200.00%) + liveins: $value_stack + CATCHRET %bb.7, %bb.1, implicit-def dead $arguments + + bb.6: + ; predecessors: %bb.3 + successors: %bb.12, %bb.11 + liveins: $value_stack + BR %bb.12, implicit-def dead $arguments + + bb.7: + ; predecessors: %bb.2, %bb.5 + successors: %bb.9(0x80000000); %bb.9(200.00%) + liveins: $value_stack + CATCHRET %bb.9, %bb.0, implicit-def dead $arguments + + bb.8: + ; predecessors: %bb.1 + liveins: $value_stack + UNREACHABLE implicit-def $arguments + + bb.9: + ; predecessors: %bb.0, %bb.7 + liveins: $value_stack + RETURN_VOID implicit-def $arguments + + bb.10 (landing-pad): + ; predecessors: %bb.4 + successors: %bb.11 + liveins: $value_stack + CATCH_ALL implicit-def $arguments + CLEANUPRET implicit-def dead $arguments + + bb.11 (landing-pad): + ; predecessors: %bb.2, %bb.6, %bb.10 + liveins: $value_stack + CATCH_ALL implicit-def $arguments + CLEANUPRET implicit-def dead $arguments + + bb.12: + ; predecessors: %bb.6 + liveins: $value_stack + UNREACHABLE implicit-def $arguments +)MIR"; + + LLVMContext Context; + std::unique_ptr<MIRParser> MIR; + MachineModuleInfo MMI(TM.get()); + std::unique_ptr<Module> M = + parseMIR(Context, MIR, *TM, MIRString, "test1", MMI); + ASSERT_TRUE(M); + + Function *F = M->getFunction("test1"); + auto *MF = MMI.getMachineFunction(*F); + ASSERT_TRUE(MF); + + WebAssemblyExceptionInfo WEI; + MachineDominatorTree MDT; + MachineDominanceFrontier MDF; + MDT.runOnMachineFunction(*MF); + MDF.getBase().analyze(MDT.getBase()); + WEI.recalculate(MDT, MDF); + + // Exception info structure: + // |- bb1 (ehpad), bb2, bb3, bb4, bb5, bb6, bb7, bb8, bb10, bb11, bb12 + // |- bb3 (ehpad), bb4, bb5, bb6, bb10, bb12 + // |- bb10 (ehpad) + // |- bb11 (ehpad) + + auto *MBB1 = MF->getBlockNumbered(1); + auto *WE0 = WEI.getExceptionFor(MBB1); + ASSERT_TRUE(WE0); + EXPECT_EQ(WE0->getEHPad(), MBB1); + EXPECT_EQ(WE0->getParentException(), nullptr); + EXPECT_EQ(WE0->getExceptionDepth(), (unsigned)1); + + auto *MBB2 = MF->getBlockNumbered(2); + WE0 = WEI.getExceptionFor(MBB2); + ASSERT_TRUE(WE0); + EXPECT_EQ(WE0->getEHPad(), MBB1); + + auto *MBB7 = MF->getBlockNumbered(7); + WE0 = WEI.getExceptionFor(MBB7); + ASSERT_TRUE(WE0); + EXPECT_EQ(WE0->getEHPad(), MBB1); + + auto *MBB8 = MF->getBlockNumbered(8); + WE0 = WEI.getExceptionFor(MBB8); + ASSERT_TRUE(WE0); + EXPECT_EQ(WE0->getEHPad(), MBB1); + + auto *MBB3 = MF->getBlockNumbered(3); + auto *WE0_0 = WEI.getExceptionFor(MBB3); + ASSERT_TRUE(WE0_0); + EXPECT_EQ(WE0_0->getEHPad(), MBB3); + EXPECT_EQ(WE0_0->getParentException(), WE0); + EXPECT_EQ(WE0_0->getExceptionDepth(), (unsigned)2); + + auto *MBB4 = MF->getBlockNumbered(4); + WE0_0 = WEI.getExceptionFor(MBB4); + ASSERT_TRUE(WE0_0); + EXPECT_EQ(WE0_0->getEHPad(), MBB3); + + auto *MBB5 = MF->getBlockNumbered(5); + WE0_0 = WEI.getExceptionFor(MBB5); + ASSERT_TRUE(WE0_0); + EXPECT_EQ(WE0_0->getEHPad(), MBB3); + + auto *MBB6 = MF->getBlockNumbered(6); + WE0_0 = WEI.getExceptionFor(MBB6); + ASSERT_TRUE(WE0_0); + EXPECT_EQ(WE0_0->getEHPad(), MBB3); + + auto *MBB12 = MF->getBlockNumbered(12); + WE0_0 = WEI.getExceptionFor(MBB12); + ASSERT_TRUE(WE0_0); + EXPECT_EQ(WE0_0->getEHPad(), MBB3); + + auto *MBB10 = MF->getBlockNumbered(10); + auto *WE0_0_0 = WEI.getExceptionFor(MBB10); + ASSERT_TRUE(WE0_0_0); + EXPECT_EQ(WE0_0_0->getEHPad(), MBB10); + EXPECT_EQ(WE0_0_0->getParentException(), WE0_0); + EXPECT_EQ(WE0_0_0->getExceptionDepth(), (unsigned)3); + + auto *MBB11 = MF->getBlockNumbered(11); + auto *WE0_1 = WEI.getExceptionFor(MBB11); + ASSERT_TRUE(WE0_1); + EXPECT_EQ(WE0_1->getEHPad(), MBB11); + EXPECT_EQ(WE0_1->getParentException(), WE0); + EXPECT_EQ(WE0_1->getExceptionDepth(), (unsigned)2); +} + +// Terminate pad test +TEST(WebAssemblyExceptionInfoTest, TEST2) { + std::unique_ptr<TargetMachine> TM = createTargetMachine(); + ASSERT_TRUE(TM); + + StringRef MIRString = R"MIR( +--- | + target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" + target triple = "wasm32-unknown-unknown" + + declare i32 @__gxx_wasm_personality_v0(...) + declare void @_ZSt9terminatev() + declare void @__clang_call_terminate(i8*) + + define hidden void @test2() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { + unreachable + } + +... +--- +name: test2 +liveins: + - { reg: '$arguments' } + - { reg: '$value_stack' } +body: | + bb.0: + successors: %bb.3, %bb.1 + BR %bb.3, implicit-def dead $arguments + + bb.1 (landing-pad): + ; predecessors: %bb.0 + successors: %bb.2, %bb.4 + %3:i32 = CATCH_I32 0, implicit-def dead $arguments + BR %bb.2, implicit-def dead $arguments + + bb.2: + ; predecessors: %bb.1 + successors: %bb.3(0x80000000); %bb.3(200.00%) + CATCHRET %bb.3, %bb.0, implicit-def dead $arguments + + bb.3: + ; predecessors: %bb.0, %bb.2 + RETURN_VOID implicit-def $arguments + + bb.4 (landing-pad): + ; predecessors: %bb.1 + successors: %bb.5, %bb.6 + CATCH_ALL implicit-def $arguments + BR %bb.5, implicit-def dead $arguments + + bb.5: + ; predecessors: %bb.4 + CLEANUPRET implicit-def dead $arguments + + bb.6 (landing-pad): + ; predecessors: %bb.4 + successors: %bb.7(0x80000000); %bb.7(200.00%) + %6:i32 = CATCH_I32 0, implicit-def dead $arguments + CALL_VOID @__clang_call_terminate, %7:i32, implicit-def $arguments + UNREACHABLE implicit-def $arguments + + bb.7 (landing-pad): + ; predecessors: %bb.6 + CATCH_ALL implicit-def $arguments + CALL_VOID @_ZSt9terminatev, implicit-def $arguments + UNREACHABLE implicit-def $arguments +)MIR"; + + LLVMContext Context; + std::unique_ptr<MIRParser> MIR; + MachineModuleInfo MMI(TM.get()); + std::unique_ptr<Module> M = + parseMIR(Context, MIR, *TM, MIRString, "test2", MMI); + ASSERT_TRUE(M); + + Function *F = M->getFunction("test2"); + auto *MF = MMI.getMachineFunction(*F); + ASSERT_TRUE(MF); + + WebAssemblyExceptionInfo WEI; + MachineDominatorTree MDT; + MachineDominanceFrontier MDF; + MDT.runOnMachineFunction(*MF); + MDF.getBase().analyze(MDT.getBase()); + WEI.recalculate(MDT, MDF); + + // Exception info structure: + // |- bb1 (ehpad), bb2, bb4, bb5, bb6, bb7 + // |- bb4 (ehpad), bb5, bb6, bb7 + // |- bb6 (ehpad), bb7 + // + // Here, bb6 is a terminate pad with a 'catch' instruction, and bb7 is a + // terminate pad with a 'catch_all' instruction, In this case we put bb6 and + // bb7 into one exception. + + auto *MBB1 = MF->getBlockNumbered(1); + auto *WE0 = WEI.getExceptionFor(MBB1); + ASSERT_TRUE(WE0); + EXPECT_EQ(WE0->getEHPad(), MBB1); + EXPECT_EQ(WE0->getParentException(), nullptr); + EXPECT_EQ(WE0->getExceptionDepth(), (unsigned)1); + + auto *MBB2 = MF->getBlockNumbered(2); + WE0 = WEI.getExceptionFor(MBB2); + ASSERT_TRUE(WE0); + EXPECT_EQ(WE0->getEHPad(), MBB1); + + auto *MBB4 = MF->getBlockNumbered(4); + auto *WE0_0 = WEI.getExceptionFor(MBB4); + ASSERT_TRUE(WE0_0); + EXPECT_EQ(WE0_0->getEHPad(), MBB4); + EXPECT_EQ(WE0_0->getParentException(), WE0); + EXPECT_EQ(WE0_0->getExceptionDepth(), (unsigned)2); + + auto *MBB5 = MF->getBlockNumbered(5); + WE0_0 = WEI.getExceptionFor(MBB5); + ASSERT_TRUE(WE0_0); + EXPECT_EQ(WE0_0->getEHPad(), MBB4); + + auto *MBB6 = MF->getBlockNumbered(6); + auto *WE0_0_0 = WEI.getExceptionFor(MBB6); + ASSERT_TRUE(WE0_0_0); + EXPECT_EQ(WE0_0_0->getEHPad(), MBB6); + EXPECT_EQ(WE0_0_0->getParentException(), WE0_0); + EXPECT_EQ(WE0_0_0->getExceptionDepth(), (unsigned)3); + + auto *MBB7 = MF->getBlockNumbered(7); + WE0_0_0 = WEI.getExceptionFor(MBB7); + ASSERT_TRUE(WE0_0_0); + EXPECT_EQ(WE0_0_0->getEHPad(), MBB6); +} |