summaryrefslogtreecommitdiff
path: root/unittests/ExecutionEngine/Orc
diff options
context:
space:
mode:
Diffstat (limited to 'unittests/ExecutionEngine/Orc')
-rw-r--r--unittests/ExecutionEngine/Orc/CMakeLists.txt4
-rw-r--r--unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp23
-rw-r--r--unittests/ExecutionEngine/Orc/GlobalMappingLayerTest.cpp28
-rw-r--r--unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp1
-rw-r--r--unittests/ExecutionEngine/Orc/OrcCAPITest.cpp40
-rw-r--r--unittests/ExecutionEngine/Orc/OrcTestCommon.h90
-rw-r--r--unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp45
-rw-r--r--unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp8
-rw-r--r--unittests/ExecutionEngine/Orc/RemoteObjectLayerTest.cpp589
-rw-r--r--unittests/ExecutionEngine/Orc/SymbolStringPoolTest.cpp48
10 files changed, 800 insertions, 76 deletions
diff --git a/unittests/ExecutionEngine/Orc/CMakeLists.txt b/unittests/ExecutionEngine/Orc/CMakeLists.txt
index db40c4213bd7..28e07959ac7b 100644
--- a/unittests/ExecutionEngine/Orc/CMakeLists.txt
+++ b/unittests/ExecutionEngine/Orc/CMakeLists.txt
@@ -18,8 +18,10 @@ add_llvm_unittest(OrcJITTests
OrcCAPITest.cpp
OrcTestCommon.cpp
QueueChannel.cpp
+ RemoteObjectLayerTest.cpp
RPCUtilsTest.cpp
RTDyldObjectLinkingLayerTest.cpp
+ SymbolStringPoolTest.cpp
)
-target_link_libraries(OrcJITTests ${LLVM_PTHREAD_LIB})
+target_link_libraries(OrcJITTests PRIVATE ${LLVM_PTHREAD_LIB})
diff --git a/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp b/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp
index 844746f28c06..61ce310e6311 100644
--- a/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp
+++ b/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp
@@ -21,7 +21,7 @@ public:
DummyCallbackManager() : JITCompileCallbackManager(0) {}
public:
- void grow() override { llvm_unreachable("not implemented"); }
+ Error grow() override { llvm_unreachable("not implemented"); }
};
class DummyStubsManager : public orc::IndirectStubsManager {
@@ -49,21 +49,18 @@ public:
};
TEST(CompileOnDemandLayerTest, FindSymbol) {
- auto MockBaseLayer = createMockBaseLayer<int>(
- DoNothingAndReturn<int>(0),
- [](int Handle) { return Error::success(); },
- [](const std::string &Name, bool) {
- if (Name == "foo")
- return JITSymbol(1, JITSymbolFlags::Exported);
- return JITSymbol(nullptr);
- },
- ReturnNullJITSymbol());
+ MockBaseLayer<int, std::shared_ptr<Module>> TestBaseLayer;
+ TestBaseLayer.findSymbolImpl =
+ [](const std::string &Name, bool) {
+ if (Name == "foo")
+ return JITSymbol(1, JITSymbolFlags::Exported);
+ return JITSymbol(nullptr);
+ };
- typedef decltype(MockBaseLayer) MockBaseLayerT;
DummyCallbackManager CallbackMgr;
- llvm::orc::CompileOnDemandLayer<MockBaseLayerT> COD(
- MockBaseLayer, [](Function &F) { return std::set<Function *>{&F}; },
+ llvm::orc::CompileOnDemandLayer<decltype(TestBaseLayer)> COD(
+ TestBaseLayer, [](Function &F) { return std::set<Function *>{&F}; },
CallbackMgr, [] { return llvm::make_unique<DummyStubsManager>(); }, true);
auto Sym = COD.findSymbol("foo", true);
diff --git a/unittests/ExecutionEngine/Orc/GlobalMappingLayerTest.cpp b/unittests/ExecutionEngine/Orc/GlobalMappingLayerTest.cpp
index 2756999c2160..d093b2a99bd7 100644
--- a/unittests/ExecutionEngine/Orc/GlobalMappingLayerTest.cpp
+++ b/unittests/ExecutionEngine/Orc/GlobalMappingLayerTest.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/GlobalMappingLayer.h"
+#include "OrcTestCommon.h"
#include "gtest/gtest.h"
using namespace llvm;
@@ -15,21 +16,26 @@ using namespace llvm::orc;
namespace {
-struct MockBaseLayer {
+TEST(GlobalMappingLayerTest, Empty) {
+ MockBaseLayer<int, std::shared_ptr<Module>> TestBaseLayer;
- typedef int ModuleHandleT;
+ TestBaseLayer.addModuleImpl =
+ [](std::shared_ptr<Module> M, std::shared_ptr<JITSymbolResolver> R) {
+ return 42;
+ };
- JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
- if (Name == "bar")
- return llvm::JITSymbol(0x4567, JITSymbolFlags::Exported);
- return nullptr;
- }
+ TestBaseLayer.findSymbolImpl =
+ [](const std::string &Name, bool ExportedSymbolsOnly) -> JITSymbol {
+ if (Name == "bar")
+ return llvm::JITSymbol(0x4567, JITSymbolFlags::Exported);
+ return nullptr;
+ };
-};
+ GlobalMappingLayer<decltype(TestBaseLayer)> L(TestBaseLayer);
-TEST(GlobalMappingLayerTest, Empty) {
- MockBaseLayer M;
- GlobalMappingLayer<MockBaseLayer> L(M);
+ // Test addModule interface.
+ int H = cantFail(L.addModule(nullptr, nullptr));
+ EXPECT_EQ(H, 42) << "Incorrect result from addModule";
// Test fall-through for missing symbol.
auto FooSym = L.findSymbol("foo", true);
diff --git a/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp b/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp
index 25103f79ac6c..7cd6443b5d4a 100644
--- a/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp
+++ b/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp
@@ -10,7 +10,6 @@
#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/NullResolver.h"
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
diff --git a/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp b/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp
index 5a4d6b4a2252..d9448d47667f 100644
--- a/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp
+++ b/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "OrcTestCommon.h"
+#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm-c/Core.h"
#include "llvm-c/OrcBindings.h"
#include "llvm-c/Target.h"
@@ -37,6 +38,15 @@ protected:
return MB.takeModule();
}
+ std::shared_ptr<object::OwningBinary<object::ObjectFile>>
+ createTestObject() {
+ orc::SimpleCompiler IRCompiler(*TM);
+ auto M = createTestModule(TM->getTargetTriple());
+ M->setDataLayout(TM->createDataLayout());
+ return std::make_shared<object::OwningBinary<object::ObjectFile>>(
+ IRCompiler(*M));
+ }
+
typedef int (*MainFnTy)();
static int myTestFuncImpl() {
@@ -134,6 +144,36 @@ TEST_F(OrcCAPIExecutionTest, TestLazyIRCompilation) {
LLVMOrcDisposeInstance(JIT);
}
+TEST_F(OrcCAPIExecutionTest, TestAddObjectFile) {
+ if (!TM)
+ return;
+
+ std::unique_ptr<MemoryBuffer> ObjBuffer;
+ {
+ auto OwningObj = createTestObject();
+ auto ObjAndBuffer = OwningObj->takeBinary();
+ ObjBuffer = std::move(ObjAndBuffer.second);
+ }
+
+ LLVMOrcJITStackRef JIT =
+ LLVMOrcCreateInstance(wrap(TM.get()));
+ LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
+
+ LLVMOrcModuleHandle H;
+ LLVMOrcAddObjectFile(JIT, &H, wrap(ObjBuffer.release()), myResolver, nullptr);
+ LLVMOrcTargetAddress MainAddr;
+ LLVMOrcGetSymbolAddress(JIT, &MainAddr, "main");
+ MainFnTy MainFn = (MainFnTy)MainAddr;
+ int Result = MainFn();
+ EXPECT_EQ(Result, 42)
+ << "Lazily JIT'd code did not return expected result";
+
+ LLVMOrcRemoveModule(JIT, H);
+
+ LLVMOrcDisposeMangledSymbol(testFuncName);
+ LLVMOrcDisposeInstance(JIT);
+}
+
TEST_F(OrcCAPIExecutionTest, TestDirectCallbacksAPI) {
if (!TM)
return;
diff --git a/unittests/ExecutionEngine/Orc/OrcTestCommon.h b/unittests/ExecutionEngine/Orc/OrcTestCommon.h
index 6c6b4918c205..28a5f08ee439 100644
--- a/unittests/ExecutionEngine/Orc/OrcTestCommon.h
+++ b/unittests/ExecutionEngine/Orc/OrcTestCommon.h
@@ -105,73 +105,63 @@ public:
}
};
-template <typename HandleT,
- typename AddModuleFtor,
- typename RemoveModuleFtor,
- typename FindSymbolFtor,
- typename FindSymbolInFtor>
+template <typename HandleT, typename ModuleT>
class MockBaseLayer {
public:
- typedef HandleT ModuleHandleT;
-
- MockBaseLayer(AddModuleFtor &&AddModule,
- RemoveModuleFtor &&RemoveModule,
- FindSymbolFtor &&FindSymbol,
- FindSymbolInFtor &&FindSymbolIn)
- : AddModule(std::move(AddModule)),
- RemoveModule(std::move(RemoveModule)),
- FindSymbol(std::move(FindSymbol)),
- FindSymbolIn(std::move(FindSymbolIn))
- {}
-
- template <typename ModuleT, typename MemoryManagerPtrT,
- typename SymbolResolverPtrT>
- Expected<ModuleHandleT> addModule(ModuleT Ms, MemoryManagerPtrT MemMgr,
- SymbolResolverPtrT Resolver) {
- return AddModule(std::move(Ms), std::move(MemMgr), std::move(Resolver));
+ using ModuleHandleT = HandleT;
+
+ using AddModuleSignature =
+ Expected<ModuleHandleT>(ModuleT M,
+ std::shared_ptr<JITSymbolResolver> R);
+
+ using RemoveModuleSignature = Error(ModuleHandleT H);
+ using FindSymbolSignature = JITSymbol(const std::string &Name,
+ bool ExportedSymbolsOnly);
+ using FindSymbolInSignature = JITSymbol(ModuleHandleT H,
+ const std::string &Name,
+ bool ExportedSymbolsONly);
+ using EmitAndFinalizeSignature = Error(ModuleHandleT H);
+
+ std::function<AddModuleSignature> addModuleImpl;
+ std::function<RemoveModuleSignature> removeModuleImpl;
+ std::function<FindSymbolSignature> findSymbolImpl;
+ std::function<FindSymbolInSignature> findSymbolInImpl;
+ std::function<EmitAndFinalizeSignature> emitAndFinalizeImpl;
+
+ Expected<ModuleHandleT> addModule(ModuleT M,
+ std::shared_ptr<JITSymbolResolver> R) {
+ assert(addModuleImpl &&
+ "addModule called, but no mock implementation was provided");
+ return addModuleImpl(std::move(M), std::move(R));
}
Error removeModule(ModuleHandleT H) {
- return RemoveModule(H);
+ assert(removeModuleImpl &&
+ "removeModule called, but no mock implementation was provided");
+ return removeModuleImpl(H);
}
JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
- return FindSymbol(Name, ExportedSymbolsOnly);
+ assert(findSymbolImpl &&
+ "findSymbol called, but no mock implementation was provided");
+ return findSymbolImpl(Name, ExportedSymbolsOnly);
}
JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name,
bool ExportedSymbolsOnly) {
- return FindSymbolIn(H, Name, ExportedSymbolsOnly);
+ assert(findSymbolInImpl &&
+ "findSymbolIn called, but no mock implementation was provided");
+ return findSymbolInImpl(H, Name, ExportedSymbolsOnly);
}
-private:
- AddModuleFtor AddModule;
- RemoveModuleFtor RemoveModule;
- FindSymbolFtor FindSymbol;
- FindSymbolInFtor FindSymbolIn;
+ Error emitAndFinaliez(ModuleHandleT H) {
+ assert(emitAndFinalizeImpl &&
+ "emitAndFinalize called, but no mock implementation was provided");
+ return emitAndFinalizeImpl(H);
+ }
};
-template <typename ModuleHandleT,
- typename AddModuleFtor,
- typename RemoveModuleFtor,
- typename FindSymbolFtor,
- typename FindSymbolInFtor>
-MockBaseLayer<ModuleHandleT, AddModuleFtor, RemoveModuleFtor,
- FindSymbolFtor, FindSymbolInFtor>
-createMockBaseLayer(AddModuleFtor &&AddModule,
- RemoveModuleFtor &&RemoveModule,
- FindSymbolFtor &&FindSymbol,
- FindSymbolInFtor &&FindSymbolIn) {
- return MockBaseLayer<ModuleHandleT, AddModuleFtor, RemoveModuleFtor,
- FindSymbolFtor, FindSymbolInFtor>(
- std::forward<AddModuleFtor>(AddModule),
- std::forward<RemoveModuleFtor>(RemoveModule),
- std::forward<FindSymbolFtor>(FindSymbol),
- std::forward<FindSymbolInFtor>(FindSymbolIn));
-}
-
-
class ReturnNullJITSymbol {
public:
template <typename... Args>
diff --git a/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp b/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp
index 1c9764b555fd..7fe449b70169 100644
--- a/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp
+++ b/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp
@@ -263,6 +263,51 @@ TEST(DummyRPC, TestCallAsyncIntInt) {
ServerThread.join();
}
+TEST(DummyRPC, TestAsyncVoidBoolHandler) {
+ auto Channels = createPairedQueueChannels();
+ DummyRPCEndpoint Client(*Channels.first);
+ DummyRPCEndpoint Server(*Channels.second);
+
+ std::thread ServerThread([&]() {
+ Server.addAsyncHandler<DummyRPCAPI::VoidBool>(
+ [](std::function<Error(Error)> SendResult,
+ bool B) {
+ EXPECT_EQ(B, true) << "Server void(bool) receieved unexpected result";
+ cantFail(SendResult(Error::success()));
+ return Error::success();
+ });
+
+ {
+ // Poke the server to handle the negotiate call.
+ auto Err = Server.handleOne();
+ EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
+ }
+
+ {
+ // Poke the server to handle the VoidBool call.
+ auto Err = Server.handleOne();
+ EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)";
+ }
+ });
+
+ {
+ auto Err = Client.callAsync<DummyRPCAPI::VoidBool>(
+ [](Error Result) {
+ EXPECT_FALSE(!!Result) << "Async void(bool) response handler failed";
+ return Error::success();
+ }, true);
+ EXPECT_FALSE(!!Err) << "Client.callAsync failed for void(bool)";
+ }
+
+ {
+ // Poke the client to process the result.
+ auto Err = Client.handleOne();
+ EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)";
+ }
+
+ ServerThread.join();
+}
+
TEST(DummyRPC, TestAsyncIntIntHandler) {
auto Channels = createPairedQueueChannels();
DummyRPCEndpoint Client(*Channels.first);
diff --git a/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp b/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp
index e4b61d855c5f..ed7b327124d7 100644
--- a/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp
+++ b/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp
@@ -255,4 +255,12 @@ TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoPrematureAllocation) {
"(multiple unrelated objects loaded prior to finalization)";
}
+TEST_F(RTDyldObjectLinkingLayerExecutionTest, TestNotifyLoadedSignature) {
+ RTDyldObjectLinkingLayer ObjLayer(
+ []() { return nullptr; },
+ [](RTDyldObjectLinkingLayer::ObjHandleT,
+ const RTDyldObjectLinkingLayer::ObjectPtr &obj,
+ const RuntimeDyld::LoadedObjectInfo &info) {});
+}
+
} // end anonymous namespace
diff --git a/unittests/ExecutionEngine/Orc/RemoteObjectLayerTest.cpp b/unittests/ExecutionEngine/Orc/RemoteObjectLayerTest.cpp
new file mode 100644
index 000000000000..819c5f8eb34b
--- /dev/null
+++ b/unittests/ExecutionEngine/Orc/RemoteObjectLayerTest.cpp
@@ -0,0 +1,589 @@
+//===---------------------- RemoteObjectLayerTest.cpp ---------------------===//
+//
+// 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/CompileUtils.h"
+#include "llvm/ExecutionEngine/Orc/NullResolver.h"
+#include "llvm/ExecutionEngine/Orc/RemoteObjectLayer.h"
+#include "OrcTestCommon.h"
+#include "QueueChannel.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::orc;
+
+namespace {
+
+class MockObjectLayer {
+public:
+
+ using ObjHandleT = uint64_t;
+
+ using ObjectPtr =
+ std::shared_ptr<object::OwningBinary<object::ObjectFile>>;
+
+ using LookupFn = std::function<JITSymbol(StringRef, bool)>;
+ using SymbolLookupTable = std::map<ObjHandleT, LookupFn>;
+
+ using AddObjectFtor =
+ std::function<Expected<ObjHandleT>(ObjectPtr, SymbolLookupTable&)>;
+
+ class ObjectNotFound : public remote::ResourceNotFound<ObjHandleT> {
+ public:
+ ObjectNotFound(ObjHandleT H) : ResourceNotFound(H, "Object handle") {}
+ };
+
+ MockObjectLayer(AddObjectFtor AddObject)
+ : AddObject(std::move(AddObject)) {}
+
+ Expected<ObjHandleT> addObject(ObjectPtr Obj,
+ std::shared_ptr<JITSymbolResolver> Resolver) {
+ return AddObject(Obj, SymTab);
+ }
+
+ Error removeObject(ObjHandleT H) {
+ if (SymTab.count(H))
+ return Error::success();
+ else
+ return make_error<ObjectNotFound>(H);
+ }
+
+ JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
+ for (auto KV : SymTab) {
+ if (auto Sym = KV.second(Name, ExportedSymbolsOnly))
+ return Sym;
+ else if (auto Err = Sym.takeError())
+ return std::move(Err);
+ }
+ return JITSymbol(nullptr);
+ }
+
+ JITSymbol findSymbolIn(ObjHandleT H, StringRef Name,
+ bool ExportedSymbolsOnly) {
+ auto LI = SymTab.find(H);
+ if (LI != SymTab.end())
+ return LI->second(Name, ExportedSymbolsOnly);
+ else
+ return make_error<ObjectNotFound>(H);
+ }
+
+ Error emitAndFinalize(ObjHandleT H) {
+ if (SymTab.count(H))
+ return Error::success();
+ else
+ return make_error<ObjectNotFound>(H);
+ }
+
+private:
+ AddObjectFtor AddObject;
+ SymbolLookupTable SymTab;
+};
+
+using RPCEndpoint = rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>;
+
+MockObjectLayer::ObjectPtr createTestObject() {
+ OrcNativeTarget::initialize();
+ auto TM = std::unique_ptr<TargetMachine>(EngineBuilder().selectTarget());
+
+ if (!TM)
+ return nullptr;
+
+ LLVMContext Ctx;
+ ModuleBuilder MB(Ctx, TM->getTargetTriple().str(), "TestModule");
+ MB.getModule()->setDataLayout(TM->createDataLayout());
+ auto *Main = MB.createFunctionDecl<void(int, char**)>("main");
+ Main->getBasicBlockList().push_back(BasicBlock::Create(Ctx));
+ IRBuilder<> B(&Main->back());
+ B.CreateRet(ConstantInt::getSigned(Type::getInt32Ty(Ctx), 42));
+
+ SimpleCompiler IRCompiler(*TM);
+ return std::make_shared<object::OwningBinary<object::ObjectFile>>(
+ IRCompiler(*MB.getModule()));
+}
+
+TEST(RemoteObjectLayer, AddObject) {
+ llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();
+ auto TestObject = createTestObject();
+ if (!TestObject)
+ return;
+
+ auto Channels = createPairedQueueChannels();
+
+ auto ReportError =
+ [](Error Err) {
+ logAllUnhandledErrors(std::move(Err), llvm::errs(), "");
+ };
+
+ // Copy the bytes out of the test object: the copy will be used to verify
+ // that the original is correctly transmitted over RPC to the mock layer.
+ StringRef ObjBytes = TestObject->getBinary()->getData();
+ std::vector<char> ObjContents(ObjBytes.size());
+ std::copy(ObjBytes.begin(), ObjBytes.end(), ObjContents.begin());
+
+ RPCEndpoint ClientEP(*Channels.first, true);
+ RemoteObjectClientLayer<RPCEndpoint> Client(ClientEP, ReportError);
+
+ RPCEndpoint ServerEP(*Channels.second, true);
+ MockObjectLayer BaseLayer(
+ [&ObjContents](MockObjectLayer::ObjectPtr Obj,
+ MockObjectLayer::SymbolLookupTable &SymTab) {
+
+ // Check that the received object file content matches the original.
+ StringRef RPCObjContents = Obj->getBinary()->getData();
+ EXPECT_EQ(RPCObjContents.size(), ObjContents.size())
+ << "RPC'd object file has incorrect size";
+ EXPECT_TRUE(std::equal(RPCObjContents.begin(), RPCObjContents.end(),
+ ObjContents.begin()))
+ << "RPC'd object file content does not match original content";
+
+ return 1;
+ });
+ RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(BaseLayer,
+ ServerEP,
+ ReportError);
+
+ bool Finished = false;
+ ServerEP.addHandler<remote::utils::TerminateSession>(
+ [&]() { Finished = true; }
+ );
+
+ auto ServerThread =
+ std::thread([&]() {
+ while (!Finished)
+ cantFail(ServerEP.handleOne());
+ });
+
+ cantFail(Client.addObject(std::move(TestObject),
+ std::make_shared<NullResolver>()));
+ cantFail(ClientEP.callB<remote::utils::TerminateSession>());
+ ServerThread.join();
+}
+
+TEST(RemoteObjectLayer, AddObjectFailure) {
+ llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();
+ auto TestObject = createTestObject();
+ if (!TestObject)
+ return;
+
+ auto Channels = createPairedQueueChannels();
+
+ auto ReportError =
+ [](Error Err) {
+ auto ErrMsg = toString(std::move(Err));
+ EXPECT_EQ(ErrMsg, "AddObjectFailure - Test Message")
+ << "Expected error string to be \"AddObjectFailure - Test Message\"";
+ };
+
+ RPCEndpoint ClientEP(*Channels.first, true);
+ RemoteObjectClientLayer<RPCEndpoint> Client(ClientEP, ReportError);
+
+ RPCEndpoint ServerEP(*Channels.second, true);
+ MockObjectLayer BaseLayer(
+ [](MockObjectLayer::ObjectPtr Obj,
+ MockObjectLayer::SymbolLookupTable &SymTab)
+ -> Expected<MockObjectLayer::ObjHandleT> {
+ return make_error<StringError>("AddObjectFailure - Test Message",
+ inconvertibleErrorCode());
+ });
+ RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(BaseLayer,
+ ServerEP,
+ ReportError);
+
+ bool Finished = false;
+ ServerEP.addHandler<remote::utils::TerminateSession>(
+ [&]() { Finished = true; }
+ );
+
+ auto ServerThread =
+ std::thread([&]() {
+ while (!Finished)
+ cantFail(ServerEP.handleOne());
+ });
+
+ auto HandleOrErr =
+ Client.addObject(std::move(TestObject), std::make_shared<NullResolver>());
+
+ EXPECT_FALSE(HandleOrErr) << "Expected error from addObject";
+
+ auto ErrMsg = toString(HandleOrErr.takeError());
+ EXPECT_EQ(ErrMsg, "AddObjectFailure - Test Message")
+ << "Expected error string to be \"AddObjectFailure - Test Message\"";
+
+ cantFail(ClientEP.callB<remote::utils::TerminateSession>());
+ ServerThread.join();
+}
+
+
+TEST(RemoteObjectLayer, RemoveObject) {
+ llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();
+ auto TestObject = createTestObject();
+ if (!TestObject)
+ return;
+
+ auto Channels = createPairedQueueChannels();
+
+ auto ReportError =
+ [](Error Err) {
+ logAllUnhandledErrors(std::move(Err), llvm::errs(), "");
+ };
+
+ RPCEndpoint ClientEP(*Channels.first, true);
+ RemoteObjectClientLayer<RPCEndpoint> Client(ClientEP, ReportError);
+
+ RPCEndpoint ServerEP(*Channels.second, true);
+
+ MockObjectLayer BaseLayer(
+ [](MockObjectLayer::ObjectPtr Obj,
+ MockObjectLayer::SymbolLookupTable &SymTab) {
+ SymTab[1] = MockObjectLayer::LookupFn();
+ return 1;
+ });
+ RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(BaseLayer,
+ ServerEP,
+ ReportError);
+
+ bool Finished = false;
+ ServerEP.addHandler<remote::utils::TerminateSession>(
+ [&]() { Finished = true; }
+ );
+
+ auto ServerThread =
+ std::thread([&]() {
+ while (!Finished)
+ cantFail(ServerEP.handleOne());
+ });
+
+ auto H = cantFail(Client.addObject(std::move(TestObject),
+ std::make_shared<NullResolver>()));
+
+ cantFail(Client.removeObject(H));
+
+ cantFail(ClientEP.callB<remote::utils::TerminateSession>());
+ ServerThread.join();
+}
+
+TEST(RemoteObjectLayer, RemoveObjectFailure) {
+ llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();
+ auto TestObject = createTestObject();
+ if (!TestObject)
+ return;
+
+ auto Channels = createPairedQueueChannels();
+
+ auto ReportError =
+ [](Error Err) {
+ auto ErrMsg = toString(std::move(Err));
+ EXPECT_EQ(ErrMsg, "Object handle 42 not found")
+ << "Expected error string to be \"Object handle 42 not found\"";
+ };
+
+ RPCEndpoint ClientEP(*Channels.first, true);
+ RemoteObjectClientLayer<RPCEndpoint> Client(ClientEP, ReportError);
+
+ RPCEndpoint ServerEP(*Channels.second, true);
+
+ // AddObject lambda does not update symbol table, so removeObject will treat
+ // this as a bad object handle.
+ MockObjectLayer BaseLayer(
+ [](MockObjectLayer::ObjectPtr Obj,
+ MockObjectLayer::SymbolLookupTable &SymTab) {
+ return 42;
+ });
+ RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(BaseLayer,
+ ServerEP,
+ ReportError);
+
+ bool Finished = false;
+ ServerEP.addHandler<remote::utils::TerminateSession>(
+ [&]() { Finished = true; }
+ );
+
+ auto ServerThread =
+ std::thread([&]() {
+ while (!Finished)
+ cantFail(ServerEP.handleOne());
+ });
+
+ auto H = cantFail(Client.addObject(std::move(TestObject),
+ std::make_shared<NullResolver>()));
+
+ auto Err = Client.removeObject(H);
+ EXPECT_TRUE(!!Err) << "Expected error from removeObject";
+
+ auto ErrMsg = toString(std::move(Err));
+ EXPECT_EQ(ErrMsg, "Object handle 42 not found")
+ << "Expected error string to be \"Object handle 42 not found\"";
+
+ cantFail(ClientEP.callB<remote::utils::TerminateSession>());
+ ServerThread.join();
+}
+
+TEST(RemoteObjectLayer, FindSymbol) {
+ llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();
+ auto TestObject = createTestObject();
+ if (!TestObject)
+ return;
+
+ auto Channels = createPairedQueueChannels();
+
+ auto ReportError =
+ [](Error Err) {
+ auto ErrMsg = toString(std::move(Err));
+ EXPECT_EQ(ErrMsg, "Could not find symbol 'badsymbol'")
+ << "Expected error string to be \"Object handle 42 not found\"";
+ };
+
+ RPCEndpoint ClientEP(*Channels.first, true);
+ RemoteObjectClientLayer<RPCEndpoint> Client(ClientEP, ReportError);
+
+ RPCEndpoint ServerEP(*Channels.second, true);
+
+ // AddObject lambda does not update symbol table, so removeObject will treat
+ // this as a bad object handle.
+ MockObjectLayer BaseLayer(
+ [](MockObjectLayer::ObjectPtr Obj,
+ MockObjectLayer::SymbolLookupTable &SymTab) {
+ SymTab[42] =
+ [](StringRef Name, bool ExportedSymbolsOnly) -> JITSymbol {
+ if (Name == "foobar")
+ return JITSymbol(0x12348765, JITSymbolFlags::Exported);
+ if (Name == "badsymbol")
+ return make_error<JITSymbolNotFound>(Name);
+ return nullptr;
+ };
+ return 42;
+ });
+ RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(BaseLayer,
+ ServerEP,
+ ReportError);
+
+ bool Finished = false;
+ ServerEP.addHandler<remote::utils::TerminateSession>(
+ [&]() { Finished = true; }
+ );
+
+ auto ServerThread =
+ std::thread([&]() {
+ while (!Finished)
+ cantFail(ServerEP.handleOne());
+ });
+
+ cantFail(Client.addObject(std::move(TestObject),
+ std::make_shared<NullResolver>()));
+
+ // Check that we can find and materialize a valid symbol.
+ auto Sym1 = Client.findSymbol("foobar", true);
+ EXPECT_TRUE(!!Sym1) << "Symbol 'foobar' should be findable";
+ EXPECT_EQ(cantFail(Sym1.getAddress()), 0x12348765ULL)
+ << "Symbol 'foobar' does not return the correct address";
+
+ {
+ // Check that we can return a symbol containing an error.
+ auto Sym2 = Client.findSymbol("badsymbol", true);
+ EXPECT_FALSE(!!Sym2) << "Symbol 'badsymbol' should not be findable";
+ auto Err = Sym2.takeError();
+ EXPECT_TRUE(!!Err) << "Sym2 should contain an error value";
+ auto ErrMsg = toString(std::move(Err));
+ EXPECT_EQ(ErrMsg, "Could not find symbol 'badsymbol'")
+ << "Expected symbol-not-found error for Sym2";
+ }
+
+ {
+ // Check that we can return a 'null' symbol.
+ auto Sym3 = Client.findSymbol("baz", true);
+ EXPECT_FALSE(!!Sym3) << "Symbol 'baz' should convert to false";
+ auto Err = Sym3.takeError();
+ EXPECT_FALSE(!!Err) << "Symbol 'baz' should not contain an error";
+ }
+
+ cantFail(ClientEP.callB<remote::utils::TerminateSession>());
+ ServerThread.join();
+}
+
+TEST(RemoteObjectLayer, FindSymbolIn) {
+ llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();
+ auto TestObject = createTestObject();
+ if (!TestObject)
+ return;
+
+ auto Channels = createPairedQueueChannels();
+
+ auto ReportError =
+ [](Error Err) {
+ auto ErrMsg = toString(std::move(Err));
+ EXPECT_EQ(ErrMsg, "Could not find symbol 'barbaz'")
+ << "Expected error string to be \"Object handle 42 not found\"";
+ };
+
+ RPCEndpoint ClientEP(*Channels.first, true);
+ RemoteObjectClientLayer<RPCEndpoint> Client(ClientEP, ReportError);
+
+ RPCEndpoint ServerEP(*Channels.second, true);
+
+ // AddObject lambda does not update symbol table, so removeObject will treat
+ // this as a bad object handle.
+ MockObjectLayer BaseLayer(
+ [](MockObjectLayer::ObjectPtr Obj,
+ MockObjectLayer::SymbolLookupTable &SymTab) {
+ SymTab[42] =
+ [](StringRef Name, bool ExportedSymbolsOnly) -> JITSymbol {
+ if (Name == "foobar")
+ return JITSymbol(0x12348765, JITSymbolFlags::Exported);
+ return make_error<JITSymbolNotFound>(Name);
+ };
+ // Dummy symbol table entry - this should not be visible to
+ // findSymbolIn.
+ SymTab[43] =
+ [](StringRef Name, bool ExportedSymbolsOnly) -> JITSymbol {
+ if (Name == "barbaz")
+ return JITSymbol(0xdeadbeef, JITSymbolFlags::Exported);
+ return make_error<JITSymbolNotFound>(Name);
+ };
+
+ return 42;
+ });
+ RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(BaseLayer,
+ ServerEP,
+ ReportError);
+
+ bool Finished = false;
+ ServerEP.addHandler<remote::utils::TerminateSession>(
+ [&]() { Finished = true; }
+ );
+
+ auto ServerThread =
+ std::thread([&]() {
+ while (!Finished)
+ cantFail(ServerEP.handleOne());
+ });
+
+ auto H = cantFail(Client.addObject(std::move(TestObject),
+ std::make_shared<NullResolver>()));
+
+ auto Sym1 = Client.findSymbolIn(H, "foobar", true);
+
+ EXPECT_TRUE(!!Sym1) << "Symbol 'foobar' should be findable";
+ EXPECT_EQ(cantFail(Sym1.getAddress()), 0x12348765ULL)
+ << "Symbol 'foobar' does not return the correct address";
+
+ auto Sym2 = Client.findSymbolIn(H, "barbaz", true);
+ EXPECT_FALSE(!!Sym2) << "Symbol 'barbaz' should not be findable";
+ auto Err = Sym2.takeError();
+ EXPECT_TRUE(!!Err) << "Sym2 should contain an error value";
+ auto ErrMsg = toString(std::move(Err));
+ EXPECT_EQ(ErrMsg, "Could not find symbol 'barbaz'")
+ << "Expected symbol-not-found error for Sym2";
+
+ cantFail(ClientEP.callB<remote::utils::TerminateSession>());
+ ServerThread.join();
+}
+
+TEST(RemoteObjectLayer, EmitAndFinalize) {
+ llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();
+ auto TestObject = createTestObject();
+ if (!TestObject)
+ return;
+
+ auto Channels = createPairedQueueChannels();
+
+ auto ReportError =
+ [](Error Err) {
+ logAllUnhandledErrors(std::move(Err), llvm::errs(), "");
+ };
+
+ RPCEndpoint ClientEP(*Channels.first, true);
+ RemoteObjectClientLayer<RPCEndpoint> Client(ClientEP, ReportError);
+
+ RPCEndpoint ServerEP(*Channels.second, true);
+
+ MockObjectLayer BaseLayer(
+ [](MockObjectLayer::ObjectPtr Obj,
+ MockObjectLayer::SymbolLookupTable &SymTab) {
+ SymTab[1] = MockObjectLayer::LookupFn();
+ return 1;
+ });
+ RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(BaseLayer,
+ ServerEP,
+ ReportError);
+
+ bool Finished = false;
+ ServerEP.addHandler<remote::utils::TerminateSession>(
+ [&]() { Finished = true; }
+ );
+
+ auto ServerThread =
+ std::thread([&]() {
+ while (!Finished)
+ cantFail(ServerEP.handleOne());
+ });
+
+ auto H = cantFail(Client.addObject(std::move(TestObject),
+ std::make_shared<NullResolver>()));
+
+ auto Err = Client.emitAndFinalize(H);
+ EXPECT_FALSE(!!Err) << "emitAndFinalize should work";
+
+ cantFail(ClientEP.callB<remote::utils::TerminateSession>());
+ ServerThread.join();
+}
+
+TEST(RemoteObjectLayer, EmitAndFinalizeFailure) {
+ llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();
+ auto TestObject = createTestObject();
+ if (!TestObject)
+ return;
+
+ auto Channels = createPairedQueueChannels();
+
+ auto ReportError =
+ [](Error Err) {
+ auto ErrMsg = toString(std::move(Err));
+ EXPECT_EQ(ErrMsg, "Object handle 1 not found")
+ << "Expected bad handle error";
+ };
+
+ RPCEndpoint ClientEP(*Channels.first, true);
+ RemoteObjectClientLayer<RPCEndpoint> Client(ClientEP, ReportError);
+
+ RPCEndpoint ServerEP(*Channels.second, true);
+
+ MockObjectLayer BaseLayer(
+ [](MockObjectLayer::ObjectPtr Obj,
+ MockObjectLayer::SymbolLookupTable &SymTab) {
+ return 1;
+ });
+ RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(BaseLayer,
+ ServerEP,
+ ReportError);
+
+ bool Finished = false;
+ ServerEP.addHandler<remote::utils::TerminateSession>(
+ [&]() { Finished = true; }
+ );
+
+ auto ServerThread =
+ std::thread([&]() {
+ while (!Finished)
+ cantFail(ServerEP.handleOne());
+ });
+
+ auto H = cantFail(Client.addObject(std::move(TestObject),
+ std::make_shared<NullResolver>()));
+
+ auto Err = Client.emitAndFinalize(H);
+ EXPECT_TRUE(!!Err) << "emitAndFinalize should work";
+
+ auto ErrMsg = toString(std::move(Err));
+ EXPECT_EQ(ErrMsg, "Object handle 1 not found")
+ << "emitAndFinalize returned incorrect error";
+
+ cantFail(ClientEP.callB<remote::utils::TerminateSession>());
+ ServerThread.join();
+}
+
+}
diff --git a/unittests/ExecutionEngine/Orc/SymbolStringPoolTest.cpp b/unittests/ExecutionEngine/Orc/SymbolStringPoolTest.cpp
new file mode 100644
index 000000000000..79929e332182
--- /dev/null
+++ b/unittests/ExecutionEngine/Orc/SymbolStringPoolTest.cpp
@@ -0,0 +1,48 @@
+//===----- SymbolStringPoolTest.cpp - Unit tests for SymbolStringPool -----===//
+//
+// 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/SymbolStringPool.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::orc;
+
+namespace {
+
+TEST(SymbolStringPool, UniquingAndComparisons) {
+ SymbolStringPool SP;
+ auto P1 = SP.intern("hello");
+
+ std::string S("hel");
+ S += "lo";
+ auto P2 = SP.intern(S);
+
+ auto P3 = SP.intern("goodbye");
+
+ EXPECT_EQ(P1, P2) << "Failed to unique entries";
+ EXPECT_NE(P1, P3) << "Inequal pooled symbol strings comparing equal";
+
+ // We want to test that less-than comparison of SymbolStringPtrs compiles,
+ // however we can't test the actual result as this is a pointer comparison and
+ // SymbolStringPtr doesn't expose the underlying address of the string.
+ (void)(P1 < P3);
+}
+
+TEST(SymbolStringPool, ClearDeadEntries) {
+ SymbolStringPool SP;
+ {
+ auto P1 = SP.intern("s1");
+ SP.clearDeadEntries();
+ EXPECT_FALSE(SP.empty()) << "\"s1\" entry in pool should still be retained";
+ }
+ SP.clearDeadEntries();
+ EXPECT_TRUE(SP.empty()) << "pool should be empty";
+}
+
+}