summaryrefslogtreecommitdiffstats
path: root/unittests/ExecutionEngine/Orc
diff options
context:
space:
mode:
Diffstat (limited to 'unittests/ExecutionEngine/Orc')
-rw-r--r--unittests/ExecutionEngine/Orc/CMakeLists.txt1
-rw-r--r--unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp82
-rw-r--r--unittests/ExecutionEngine/Orc/OrcTestCommon.cpp6
-rw-r--r--unittests/ExecutionEngine/Orc/OrcTestCommon.h2
-rw-r--r--unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp147
5 files changed, 234 insertions, 4 deletions
diff --git a/unittests/ExecutionEngine/Orc/CMakeLists.txt b/unittests/ExecutionEngine/Orc/CMakeLists.txt
index 74cc5b5..41fef24 100644
--- a/unittests/ExecutionEngine/Orc/CMakeLists.txt
+++ b/unittests/ExecutionEngine/Orc/CMakeLists.txt
@@ -18,4 +18,5 @@ add_llvm_unittest(OrcJITTests
ObjectTransformLayerTest.cpp
OrcCAPITest.cpp
OrcTestCommon.cpp
+ RPCUtilsTest.cpp
)
diff --git a/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp b/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp
index a37177c..59ee01f 100644
--- a/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp
+++ b/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "OrcTestCommon.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
@@ -21,6 +22,19 @@ using namespace llvm::orc;
namespace {
+class ObjectLinkingLayerExecutionTest : public testing::Test,
+ public OrcExecutionTest {
+};
+
+class SectionMemoryManagerWrapper : public SectionMemoryManager {
+public:
+ int FinalizationCount = 0;
+ bool finalizeMemory(std::string *ErrMsg = 0) override {
+ ++FinalizationCount;
+ return SectionMemoryManager::finalizeMemory(ErrMsg);
+ }
+};
+
TEST(ObjectLinkingLayerTest, TestSetProcessAllSections) {
class SectionMemoryManagerWrapper : public SectionMemoryManager {
@@ -91,4 +105,72 @@ TEST(ObjectLinkingLayerTest, TestSetProcessAllSections) {
}
}
+
+TEST_F(ObjectLinkingLayerExecutionTest, NoDuplicateFinalization) {
+
+ if (!TM)
+ return;
+
+ ObjectLinkingLayer<> ObjLayer;
+ SimpleCompiler Compile(*TM);
+
+ // Create a pair of modules that will trigger recursive finalization:
+ // Module 1:
+ // int bar() { return 42; }
+ // Module 2:
+ // int bar();
+ // int foo() { return bar(); }
+
+ ModuleBuilder MB1(getGlobalContext(), "", "dummy");
+ {
+ MB1.getModule()->setDataLayout(TM->createDataLayout());
+ Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("bar");
+ BasicBlock *BarEntry = BasicBlock::Create(getGlobalContext(), "entry",
+ BarImpl);
+ IRBuilder<> Builder(BarEntry);
+ IntegerType *Int32Ty = IntegerType::get(getGlobalContext(), 32);
+ Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
+ Builder.CreateRet(FourtyTwo);
+ }
+
+ auto Obj1 = Compile(*MB1.getModule());
+ std::vector<object::ObjectFile*> Obj1Set;
+ Obj1Set.push_back(Obj1.getBinary());
+
+ ModuleBuilder MB2(getGlobalContext(), "", "dummy");
+ {
+ MB2.getModule()->setDataLayout(TM->createDataLayout());
+ Function *BarDecl = MB2.createFunctionDecl<int32_t(void)>("bar");
+ Function *FooImpl = MB2.createFunctionDecl<int32_t(void)>("foo");
+ BasicBlock *FooEntry = BasicBlock::Create(getGlobalContext(), "entry",
+ FooImpl);
+ IRBuilder<> Builder(FooEntry);
+ Builder.CreateRet(Builder.CreateCall(BarDecl));
+ }
+ auto Obj2 = Compile(*MB2.getModule());
+ std::vector<object::ObjectFile*> Obj2Set;
+ Obj2Set.push_back(Obj2.getBinary());
+
+ auto Resolver =
+ createLambdaResolver(
+ [&](const std::string &Name) {
+ if (auto Sym = ObjLayer.findSymbol(Name, true))
+ return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags());
+ return RuntimeDyld::SymbolInfo(nullptr);
+ },
+ [](const std::string &Name) {
+ return RuntimeDyld::SymbolInfo(nullptr);
+ });
+
+ SectionMemoryManagerWrapper SMMW;
+ ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &*Resolver);
+ auto H = ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &*Resolver);
+ ObjLayer.emitAndFinalize(H);
+
+ // Finalization of module 2 should trigger finalization of module 1.
+ // Verify that finalize on SMMW is only called once.
+ EXPECT_EQ(SMMW.FinalizationCount, 1)
+ << "Extra call to finalize";
+}
+
}
diff --git a/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp b/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp
index 1b5485d..17d1e9c 100644
--- a/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp
+++ b/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp
@@ -19,7 +19,7 @@ bool OrcExecutionTest::NativeTargetInitialized = false;
ModuleBuilder::ModuleBuilder(LLVMContext &Context, StringRef Triple,
StringRef Name)
- : M(new Module(Name, Context)),
- Builder(Context) {
- M->setTargetTriple(Triple);
+ : M(new Module(Name, Context)) {
+ if (Triple != "")
+ M->setTargetTriple(Triple);
}
diff --git a/unittests/ExecutionEngine/Orc/OrcTestCommon.h b/unittests/ExecutionEngine/Orc/OrcTestCommon.h
index 15d9f54..f480e07 100644
--- a/unittests/ExecutionEngine/Orc/OrcTestCommon.h
+++ b/unittests/ExecutionEngine/Orc/OrcTestCommon.h
@@ -20,6 +20,7 @@
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/TypeBuilder.h"
+#include "llvm/Object/ObjectFile.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/Orc/JITSymbol.h"
#include "llvm/Support/TargetSelect.h"
@@ -74,7 +75,6 @@ public:
private:
std::unique_ptr<Module> M;
- IRBuilder<> Builder;
};
// Dummy struct type.
diff --git a/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp b/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp
new file mode 100644
index 0000000..8215144
--- /dev/null
+++ b/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp
@@ -0,0 +1,147 @@
+//===----------- RPCUtilsTest.cpp - Unit tests the Orc RPC utils ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/RPCChannel.h"
+#include "llvm/ExecutionEngine/Orc/RPCUtils.h"
+#include "gtest/gtest.h"
+
+#include <queue>
+
+using namespace llvm;
+using namespace llvm::orc;
+using namespace llvm::orc::remote;
+
+class QueueChannel : public RPCChannel {
+public:
+ QueueChannel(std::queue<char> &Queue) : Queue(Queue) {}
+
+ std::error_code readBytes(char *Dst, unsigned Size) override {
+ while (Size--) {
+ *Dst++ = Queue.front();
+ Queue.pop();
+ }
+ return std::error_code();
+ }
+
+ std::error_code appendBytes(const char *Src, unsigned Size) override {
+ while (Size--)
+ Queue.push(*Src++);
+ return std::error_code();
+ }
+
+ std::error_code send() override { return std::error_code(); }
+
+private:
+ std::queue<char> &Queue;
+};
+
+class DummyRPC : public testing::Test,
+ public RPC<QueueChannel> {
+public:
+ typedef Procedure<1, bool> Proc1;
+ typedef Procedure<2, int8_t,
+ uint8_t,
+ int16_t,
+ uint16_t,
+ int32_t,
+ uint32_t,
+ int64_t,
+ uint64_t,
+ bool,
+ std::string,
+ std::vector<int>> AllTheTypes;
+};
+
+
+TEST_F(DummyRPC, TestBasic) {
+ std::queue<char> Queue;
+ QueueChannel C(Queue);
+
+ {
+ // Make a call to Proc1.
+ auto EC = call<Proc1>(C, true);
+ EXPECT_FALSE(EC) << "Simple call over queue failed";
+ }
+
+ {
+ // Expect a call to Proc1.
+ auto EC = expect<Proc1>(C,
+ [&](bool &B) {
+ EXPECT_EQ(B, true)
+ << "Bool serialization broken";
+ return std::error_code();
+ });
+ EXPECT_FALSE(EC) << "Simple expect over queue failed";
+ }
+}
+
+TEST_F(DummyRPC, TestSerialization) {
+ std::queue<char> Queue;
+ QueueChannel C(Queue);
+
+ {
+ // Make a call to Proc1.
+ std::vector<int> v({42, 7});
+ auto EC = call<AllTheTypes>(C,
+ -101,
+ 250,
+ -10000,
+ 10000,
+ -1000000000,
+ 1000000000,
+ -10000000000,
+ 10000000000,
+ true,
+ "foo",
+ v);
+ EXPECT_FALSE(EC) << "Big (serialization test) call over queue failed";
+ }
+
+ {
+ // Expect a call to Proc1.
+ auto EC = expect<AllTheTypes>(C,
+ [&](int8_t &s8,
+ uint8_t &u8,
+ int16_t &s16,
+ uint16_t &u16,
+ int32_t &s32,
+ uint32_t &u32,
+ int64_t &s64,
+ uint64_t &u64,
+ bool &b,
+ std::string &s,
+ std::vector<int> &v) {
+
+ EXPECT_EQ(s8, -101)
+ << "int8_t serialization broken";
+ EXPECT_EQ(u8, 250)
+ << "uint8_t serialization broken";
+ EXPECT_EQ(s16, -10000)
+ << "int16_t serialization broken";
+ EXPECT_EQ(u16, 10000)
+ << "uint16_t serialization broken";
+ EXPECT_EQ(s32, -1000000000)
+ << "int32_t serialization broken";
+ EXPECT_EQ(u32, 1000000000ULL)
+ << "uint32_t serialization broken";
+ EXPECT_EQ(s64, -10000000000)
+ << "int64_t serialization broken";
+ EXPECT_EQ(u64, 10000000000ULL)
+ << "uint64_t serialization broken";
+ EXPECT_EQ(b, true)
+ << "bool serialization broken";
+ EXPECT_EQ(s, "foo")
+ << "std::string serialization broken";
+ EXPECT_EQ(v, std::vector<int>({42, 7}))
+ << "std::vector serialization broken";
+ return std::error_code();
+ });
+ EXPECT_FALSE(EC) << "Big (serialization test) call over queue failed";
+ }
+}
OpenPOWER on IntegriCloud