This moves the registry higher in the LLVM library dependency stack. Every client of the target registry needs to link against MC anyway to actually use the target, so we might as well move this out of Support. This allows us to ensure that Support doesn't have includes from MC/*. Differential Revision: https://reviews.llvm.org/D111454
418 lines
12 KiB
C++
418 lines
12 KiB
C++
//=== WebAssemblyExceptionInfoTest.cpp - WebAssemblyExceptionInfo unit tests =//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#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/MC/TargetRegistry.h"
|
|
#include "llvm/Support/SourceMgr.h"
|
|
#include "llvm/Support/TargetSelect.h"
|
|
#include "llvm/Target/TargetMachine.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
|
|
std::unique_ptr<LLVMTargetMachine> 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<LLVMTargetMachine>(static_cast<LLVMTargetMachine*>(
|
|
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<LLVMTargetMachine> 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 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
|
|
RETHROW 0, implicit-def dead $arguments
|
|
|
|
bb.3 (landing-pad):
|
|
; predecessors: %bb.2
|
|
successors: %bb.4, %bb.6
|
|
liveins: $value_stack
|
|
%1:i32 = CATCH &__cpp_exception, 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
|
|
BR %bb.7, 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 implicit-def $arguments
|
|
|
|
bb.8 (landing-pad):
|
|
; predecessors: %bb.4
|
|
successors: %bb.9
|
|
liveins: $value_stack
|
|
CATCH_ALL implicit-def $arguments
|
|
RETHROW 0, implicit-def dead $arguments
|
|
|
|
bb.9 (landing-pad):
|
|
; predecessors: %bb.2, %bb.6, %bb.8
|
|
liveins: $value_stack
|
|
CATCH_ALL implicit-def $arguments
|
|
RETHROW 0, 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(*MF, 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<LLVMTargetMachine> 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 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
|
|
%0:i32 = CATCH &__cpp_exception, implicit-def $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
|
|
%1:i32 = CATCH &__cpp_exception, 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
|
|
BR %bb.7, 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
|
|
BR %bb.9, 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 implicit-def $arguments
|
|
|
|
bb.10 (landing-pad):
|
|
; predecessors: %bb.4
|
|
successors: %bb.11
|
|
liveins: $value_stack
|
|
CATCH_ALL implicit-def $arguments
|
|
RETHROW 0, implicit-def dead $arguments
|
|
|
|
bb.11 (landing-pad):
|
|
; predecessors: %bb.2, %bb.6, %bb.10
|
|
liveins: $value_stack
|
|
CATCH_ALL implicit-def $arguments
|
|
RETHROW 0, 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(*MF, 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);
|
|
}
|