diff options
| author | 2016-09-03 22:46:54 +0000 | |
|---|---|---|
| committer | 2016-09-03 22:46:54 +0000 | |
| commit | b5500b9ca0102f1ccaf32f0e77e96d0739aded9b (patch) | |
| tree | e1b7ebb5a0231f9e6d8d3f6f719582cebd64dc98 /gnu/llvm/unittests/ExecutionEngine/Orc | |
| parent | clarify purpose of src/gnu/ directory. (diff) | |
| download | wireguard-openbsd-b5500b9ca0102f1ccaf32f0e77e96d0739aded9b.tar.xz wireguard-openbsd-b5500b9ca0102f1ccaf32f0e77e96d0739aded9b.zip | |
Use the space freed up by sparc and zaurus to import LLVM.
ok hackroom@
Diffstat (limited to 'gnu/llvm/unittests/ExecutionEngine/Orc')
12 files changed, 1210 insertions, 0 deletions
diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt b/gnu/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt new file mode 100644 index 00000000000..41fef24556b --- /dev/null +++ b/gnu/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt @@ -0,0 +1,22 @@ + +set(LLVM_LINK_COMPONENTS + Core + ExecutionEngine + Object + OrcJIT + RuntimeDyld + Support + native + ) + +add_llvm_unittest(OrcJITTests + CompileOnDemandLayerTest.cpp + IndirectionUtilsTest.cpp + GlobalMappingLayerTest.cpp + LazyEmittingLayerTest.cpp + ObjectLinkingLayerTest.cpp + ObjectTransformLayerTest.cpp + OrcCAPITest.cpp + OrcTestCommon.cpp + RPCUtilsTest.cpp + ) diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp b/gnu/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp new file mode 100644 index 00000000000..a27e649b616 --- /dev/null +++ b/gnu/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp @@ -0,0 +1,75 @@ +//===----- CompileOnDemandLayerTest.cpp - Unit tests for the COD layer ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "OrcTestCommon.h" +#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace llvm::orc; + +namespace { + +class DummyCallbackManager : public orc::JITCompileCallbackManager { +public: + DummyCallbackManager() : JITCompileCallbackManager(0) { } +public: + void grow() override { llvm_unreachable("not implemented"); } +}; + +class DummyStubsManager : public orc::IndirectStubsManager { +public: + std::error_code createStub(StringRef StubName, TargetAddress InitAddr, + JITSymbolFlags Flags) override { + llvm_unreachable("Not implemented"); + } + + std::error_code createStubs(const StubInitsMap &StubInits) override { + llvm_unreachable("Not implemented"); + } + + JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) override { + llvm_unreachable("Not implemented"); + } + + JITSymbol findPointer(StringRef Name) override { + llvm_unreachable("Not implemented"); + } + + std::error_code updatePointer(StringRef Name, + TargetAddress NewAddr) override { + llvm_unreachable("Not implemented"); + } +}; + +TEST(CompileOnDemandLayerTest, FindSymbol) { + auto MockBaseLayer = + createMockBaseLayer<int>(DoNothingAndReturn<int>(0), + DoNothingAndReturn<void>(), + [](const std::string &Name, bool) { + if (Name == "foo") + return JITSymbol(1, JITSymbolFlags::Exported); + return JITSymbol(nullptr); + }, + DoNothingAndReturn<JITSymbol>(nullptr)); + + typedef decltype(MockBaseLayer) MockBaseLayerT; + DummyCallbackManager CallbackMgr; + + llvm::orc::CompileOnDemandLayer<MockBaseLayerT> COD( + MockBaseLayer, [](Function &F) { return std::set<Function *>{&F}; }, + CallbackMgr, [] { return llvm::make_unique<DummyStubsManager>(); }, true); + + auto Sym = COD.findSymbol("foo", true); + + EXPECT_TRUE(!!Sym) + << "CompileOnDemand::findSymbol should call findSymbol in the base layer."; +} + +} diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/GlobalMappingLayerTest.cpp b/gnu/llvm/unittests/ExecutionEngine/Orc/GlobalMappingLayerTest.cpp new file mode 100644 index 00000000000..054fc16cabd --- /dev/null +++ b/gnu/llvm/unittests/ExecutionEngine/Orc/GlobalMappingLayerTest.cpp @@ -0,0 +1,55 @@ +//===--- GlobalMappingLayerTest.cpp - Unit test the global mapping layer --===// +// +// 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/GlobalMappingLayer.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace llvm::orc; + +namespace { + +struct MockBaseLayer { + + typedef int ModuleSetHandleT; + + JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { + if (Name == "bar") + return llvm::orc::JITSymbol(0x4567, JITSymbolFlags::Exported); + return nullptr; + } + +}; + +TEST(GlobalMappingLayerTest, Empty) { + MockBaseLayer M; + GlobalMappingLayer<MockBaseLayer> L(M); + + // Test fall-through for missing symbol. + auto FooSym = L.findSymbol("foo", true); + EXPECT_FALSE(FooSym) << "Found unexpected symbol."; + + // Test fall-through for symbol in base layer. + auto BarSym = L.findSymbol("bar", true); + EXPECT_EQ(BarSym.getAddress(), static_cast<TargetAddress>(0x4567)) + << "Symbol lookup fall-through failed."; + + // Test setup of a global mapping. + L.setGlobalMapping("foo", 0x0123); + auto FooSym2 = L.findSymbol("foo", true); + EXPECT_EQ(FooSym2.getAddress(), static_cast<TargetAddress>(0x0123)) + << "Symbol mapping setup failed."; + + // Test removal of a global mapping. + L.eraseGlobalMapping("foo"); + auto FooSym3 = L.findSymbol("foo", true); + EXPECT_FALSE(FooSym3) << "Symbol mapping removal failed."; +} + +} diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/IndirectionUtilsTest.cpp b/gnu/llvm/unittests/ExecutionEngine/Orc/IndirectionUtilsTest.cpp new file mode 100644 index 00000000000..38b60ea7fcd --- /dev/null +++ b/gnu/llvm/unittests/ExecutionEngine/Orc/IndirectionUtilsTest.cpp @@ -0,0 +1,48 @@ +//===- LazyEmittingLayerTest.cpp - Unit tests for the lazy emitting layer -===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "OrcTestCommon.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +TEST(IndirectionUtilsTest, MakeStub) { + ModuleBuilder MB(getGlobalContext(), "x86_64-apple-macosx10.10", ""); + Function *F = MB.createFunctionDecl<void(DummyStruct, DummyStruct)>(""); + SmallVector<AttributeSet, 4> Attrs; + Attrs.push_back( + AttributeSet::get(MB.getModule()->getContext(), 1U, + AttrBuilder().addAttribute(Attribute::StructRet))); + Attrs.push_back( + AttributeSet::get(MB.getModule()->getContext(), 2U, + AttrBuilder().addAttribute(Attribute::ByVal))); + Attrs.push_back( + AttributeSet::get(MB.getModule()->getContext(), ~0U, + AttrBuilder().addAttribute(Attribute::NoUnwind))); + F->setAttributes(AttributeSet::get(MB.getModule()->getContext(), Attrs)); + + auto ImplPtr = orc::createImplPointer(*F->getType(), *MB.getModule(), "", nullptr); + orc::makeStub(*F, *ImplPtr); + + auto II = F->getEntryBlock().begin(); + EXPECT_TRUE(isa<LoadInst>(*II)) << "First instruction of stub should be a load."; + auto *Call = dyn_cast<CallInst>(std::next(II)); + EXPECT_TRUE(Call != nullptr) << "Second instruction of stub should be a call."; + EXPECT_TRUE(Call->isTailCall()) << "Indirect call from stub should be tail call."; + EXPECT_TRUE(Call->hasStructRetAttr()) + << "makeStub should propagate sret attr on 1st argument."; + EXPECT_TRUE(Call->paramHasAttr(2U, Attribute::ByVal)) + << "makeStub should propagate byval attr on 2nd argument."; +} + +} diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/LazyEmittingLayerTest.cpp b/gnu/llvm/unittests/ExecutionEngine/Orc/LazyEmittingLayerTest.cpp new file mode 100644 index 00000000000..a495766db91 --- /dev/null +++ b/gnu/llvm/unittests/ExecutionEngine/Orc/LazyEmittingLayerTest.cpp @@ -0,0 +1,32 @@ +//===- LazyEmittingLayerTest.cpp - Unit tests for the lazy emitting layer -===// +// +// 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/LazyEmittingLayer.h" +#include "gtest/gtest.h" + +namespace { + +struct MockBaseLayer { + typedef int ModuleSetHandleT; + ModuleSetHandleT addModuleSet( + std::list<std::unique_ptr<llvm::Module>>, + std::unique_ptr<llvm::RuntimeDyld::MemoryManager> MemMgr, + std::unique_ptr<llvm::RuntimeDyld::SymbolResolver> Resolver) { + EXPECT_FALSE(MemMgr); + return 42; + } +}; + +TEST(LazyEmittingLayerTest, Empty) { + MockBaseLayer M; + llvm::orc::LazyEmittingLayer<MockBaseLayer> L(M); + L.addModuleSet(std::list<std::unique_ptr<llvm::Module>>(), nullptr, nullptr); +} + +} diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/Makefile b/gnu/llvm/unittests/ExecutionEngine/Orc/Makefile new file mode 100644 index 00000000000..c899728e507 --- /dev/null +++ b/gnu/llvm/unittests/ExecutionEngine/Orc/Makefile @@ -0,0 +1,16 @@ +##===- unittests/ExecutionEngine/Orc/Makefile --------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +TESTNAME = OrcJIT +LINK_COMPONENTS := core ipo mcjit orcjit native support + +include $(LEVEL)/Makefile.config +include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest + diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp b/gnu/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp new file mode 100644 index 00000000000..59ee01f3601 --- /dev/null +++ b/gnu/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp @@ -0,0 +1,176 @@ +//===-- ObjectLinkingLayerTest.cpp - Unit tests for object linking layer --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "OrcTestCommon.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "llvm/ExecutionEngine/Orc/LambdaResolver.h" +#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/LLVMContext.h" +#include "gtest/gtest.h" + +using namespace llvm; +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 { + public: + SectionMemoryManagerWrapper(bool &DebugSeen) : DebugSeen(DebugSeen) {} + uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, + StringRef SectionName, + bool IsReadOnly) override { + if (SectionName == ".debug_str") + DebugSeen = true; + return SectionMemoryManager::allocateDataSection(Size, Alignment, + SectionID, + SectionName, + IsReadOnly); + } + private: + bool DebugSeen; + }; + + ObjectLinkingLayer<> ObjLayer; + + auto M = llvm::make_unique<Module>("", getGlobalContext()); + M->setTargetTriple("x86_64-unknown-linux-gnu"); + Type *Int32Ty = IntegerType::get(getGlobalContext(), 32); + GlobalVariable *GV = + new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage, + ConstantInt::get(Int32Ty, 42), "foo"); + + GV->setSection(".debug_str"); + + std::unique_ptr<TargetMachine> TM( + EngineBuilder().selectTarget(Triple(M->getTargetTriple()), "", "", + SmallVector<std::string, 1>())); + if (!TM) + return; + + auto OwningObj = SimpleCompiler(*TM)(*M); + std::vector<object::ObjectFile*> Objs; + Objs.push_back(OwningObj.getBinary()); + + bool DebugSectionSeen = false; + SectionMemoryManagerWrapper SMMW(DebugSectionSeen); + auto Resolver = + createLambdaResolver( + [](const std::string &Name) { + return RuntimeDyld::SymbolInfo(nullptr); + }, + [](const std::string &Name) { + return RuntimeDyld::SymbolInfo(nullptr); + }); + + { + // Test with ProcessAllSections = false (the default). + auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver); + EXPECT_EQ(DebugSectionSeen, false) + << "Unexpected debug info section"; + ObjLayer.removeObjectSet(H); + } + + { + // Test with ProcessAllSections = true. + ObjLayer.setProcessAllSections(true); + auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver); + EXPECT_EQ(DebugSectionSeen, true) + << "Expected debug info section not seen"; + ObjLayer.removeObjectSet(H); + } +} + + +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/gnu/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp b/gnu/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp new file mode 100644 index 00000000000..c88c94f17b1 --- /dev/null +++ b/gnu/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp @@ -0,0 +1,275 @@ +//===- ObjectTransformLayerTest.cpp - Unit tests for ObjectTransformLayer -===// +// +// 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/ObjectTransformLayer.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "gtest/gtest.h" + +using namespace llvm::orc; + +namespace { + +// Stand-in for RuntimeDyld::MemoryManager +typedef int MockMemoryManager; + +// Stand-in for RuntimeDyld::SymbolResolver +typedef int MockSymbolResolver; + +// stand-in for object::ObjectFile +typedef int MockObjectFile; + +// stand-in for llvm::MemoryBuffer set +typedef int MockMemoryBufferSet; + +// Mock transform that operates on unique pointers to object files, and +// allocates new object files rather than mutating the given ones. +struct AllocatingTransform { + std::unique_ptr<MockObjectFile> + operator()(std::unique_ptr<MockObjectFile> Obj) const { + return llvm::make_unique<MockObjectFile>(*Obj + 1); + } +}; + +// Mock base layer for verifying behavior of transform layer. +// Each method "T foo(args)" is accompanied by two auxiliary methods: +// - "void expectFoo(args)", to be called before calling foo on the transform +// layer; saves values of args, which mock layer foo then verifies against. +// - "void verifyFoo(T)", to be called after foo, which verifies that the +// transform layer called the base layer and forwarded any return value. +class MockBaseLayer { +public: + typedef int ObjSetHandleT; + + MockBaseLayer() : MockSymbol(nullptr) { resetExpectations(); } + + template <typename ObjSetT, typename MemoryManagerPtrT, + typename SymbolResolverPtrT> + ObjSetHandleT addObjectSet(ObjSetT &Objects, MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) { + EXPECT_EQ(MockManager, *MemMgr) << "MM should pass through"; + EXPECT_EQ(MockResolver, *Resolver) << "Resolver should pass through"; + size_t I = 0; + for (auto &ObjPtr : Objects) { + EXPECT_EQ(MockObjects[I++] + 1, *ObjPtr) << "Transform should be applied"; + } + EXPECT_EQ(MockObjects.size(), I) << "Number of objects should match"; + LastCalled = "addObjectSet"; + MockObjSetHandle = 111; + return MockObjSetHandle; + } + template <typename ObjSetT> + void expectAddObjectSet(ObjSetT &Objects, MockMemoryManager *MemMgr, + MockSymbolResolver *Resolver) { + MockManager = *MemMgr; + MockResolver = *Resolver; + for (auto &ObjPtr : Objects) { + MockObjects.push_back(*ObjPtr); + } + } + void verifyAddObjectSet(ObjSetHandleT Returned) { + EXPECT_EQ("addObjectSet", LastCalled); + EXPECT_EQ(MockObjSetHandle, Returned) << "Return should pass through"; + resetExpectations(); + } + + void removeObjectSet(ObjSetHandleT H) { + EXPECT_EQ(MockObjSetHandle, H); + LastCalled = "removeObjectSet"; + } + void expectRemoveObjectSet(ObjSetHandleT H) { MockObjSetHandle = H; } + void verifyRemoveObjectSet() { + EXPECT_EQ("removeObjectSet", LastCalled); + resetExpectations(); + } + + JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { + EXPECT_EQ(MockName, Name) << "Name should pass through"; + EXPECT_EQ(MockBool, ExportedSymbolsOnly) << "Flag should pass through"; + LastCalled = "findSymbol"; + MockSymbol = JITSymbol(122, llvm::JITSymbolFlags::None); + return MockSymbol; + } + void expectFindSymbol(const std::string &Name, bool ExportedSymbolsOnly) { + MockName = Name; + MockBool = ExportedSymbolsOnly; + } + void verifyFindSymbol(llvm::orc::JITSymbol Returned) { + EXPECT_EQ("findSymbol", LastCalled); + EXPECT_EQ(MockSymbol.getAddress(), Returned.getAddress()) + << "Return should pass through"; + resetExpectations(); + } + + JITSymbol findSymbolIn(ObjSetHandleT H, const std::string &Name, + bool ExportedSymbolsOnly) { + EXPECT_EQ(MockObjSetHandle, H) << "Handle should pass through"; + EXPECT_EQ(MockName, Name) << "Name should pass through"; + EXPECT_EQ(MockBool, ExportedSymbolsOnly) << "Flag should pass through"; + LastCalled = "findSymbolIn"; + MockSymbol = JITSymbol(122, llvm::JITSymbolFlags::None); + return MockSymbol; + } + void expectFindSymbolIn(ObjSetHandleT H, const std::string &Name, + bool ExportedSymbolsOnly) { + MockObjSetHandle = H; + MockName = Name; + MockBool = ExportedSymbolsOnly; + } + void verifyFindSymbolIn(llvm::orc::JITSymbol Returned) { + EXPECT_EQ("findSymbolIn", LastCalled); + EXPECT_EQ(MockSymbol.getAddress(), Returned.getAddress()) + << "Return should pass through"; + resetExpectations(); + } + + void emitAndFinalize(ObjSetHandleT H) { + EXPECT_EQ(MockObjSetHandle, H) << "Handle should pass through"; + LastCalled = "emitAndFinalize"; + } + void expectEmitAndFinalize(ObjSetHandleT H) { MockObjSetHandle = H; } + void verifyEmitAndFinalize() { + EXPECT_EQ("emitAndFinalize", LastCalled); + resetExpectations(); + } + + void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress, + TargetAddress TargetAddr) { + EXPECT_EQ(MockObjSetHandle, H); + EXPECT_EQ(MockLocalAddress, LocalAddress); + EXPECT_EQ(MockTargetAddress, TargetAddr); + LastCalled = "mapSectionAddress"; + } + void expectMapSectionAddress(ObjSetHandleT H, const void *LocalAddress, + TargetAddress TargetAddr) { + MockObjSetHandle = H; + MockLocalAddress = LocalAddress; + MockTargetAddress = TargetAddr; + } + void verifyMapSectionAddress() { + EXPECT_EQ("mapSectionAddress", LastCalled); + resetExpectations(); + } + +private: + // Backing fields for remembering parameter/return values + std::string LastCalled; + MockMemoryManager MockManager; + MockSymbolResolver MockResolver; + std::vector<MockObjectFile> MockObjects; + ObjSetHandleT MockObjSetHandle; + std::string MockName; + bool MockBool; + JITSymbol MockSymbol; + const void *MockLocalAddress; + TargetAddress MockTargetAddress; + MockMemoryBufferSet MockBufferSet; + + // Clear remembered parameters between calls + void resetExpectations() { + LastCalled = "nothing"; + MockManager = 0; + MockResolver = 0; + MockObjects.clear(); + MockObjSetHandle = 0; + MockName = "bogus"; + MockSymbol = JITSymbol(nullptr); + MockLocalAddress = nullptr; + MockTargetAddress = 0; + MockBufferSet = 0; + } +}; + +// Test each operation on ObjectTransformLayer. +TEST(ObjectTransformLayerTest, Main) { + MockBaseLayer M; + + // Create one object transform layer using a transform (as a functor) + // that allocates new objects, and deals in unique pointers. + ObjectTransformLayer<MockBaseLayer, AllocatingTransform> T1(M); + + // Create a second object transform layer using a transform (as a lambda) + // that mutates objects in place, and deals in naked pointers + ObjectTransformLayer<MockBaseLayer, + std::function<MockObjectFile *(MockObjectFile *)>> + T2(M, [](MockObjectFile *Obj) { + ++(*Obj); + return Obj; + }); + + // Instantiate some mock objects to use below + MockObjectFile MockObject1 = 211; + MockObjectFile MockObject2 = 222; + MockMemoryManager MockManager = 233; + MockSymbolResolver MockResolver = 244; + + // Test addObjectSet with T1 (allocating, unique pointers) + std::vector<std::unique_ptr<MockObjectFile>> Objs1; + Objs1.push_back(llvm::make_unique<MockObjectFile>(MockObject1)); + Objs1.push_back(llvm::make_unique<MockObjectFile>(MockObject2)); + auto MM = llvm::make_unique<MockMemoryManager>(MockManager); + auto SR = llvm::make_unique<MockSymbolResolver>(MockResolver); + M.expectAddObjectSet(Objs1, MM.get(), SR.get()); + auto H = T1.addObjectSet(Objs1, std::move(MM), std::move(SR)); + M.verifyAddObjectSet(H); + + // Test addObjectSet with T2 (mutating, naked pointers) + llvm::SmallVector<MockObjectFile *, 2> Objs2; + Objs2.push_back(&MockObject1); + Objs2.push_back(&MockObject2); + M.expectAddObjectSet(Objs2, &MockManager, &MockResolver); + H = T2.addObjectSet(Objs2, &MockManager, &MockResolver); + M.verifyAddObjectSet(H); + EXPECT_EQ(212, MockObject1) << "Expected mutation"; + EXPECT_EQ(223, MockObject2) << "Expected mutation"; + + // Test removeObjectSet + M.expectRemoveObjectSet(H); + T1.removeObjectSet(H); + M.verifyRemoveObjectSet(); + + // Test findSymbol + std::string Name = "foo"; + bool ExportedOnly = true; + M.expectFindSymbol(Name, ExportedOnly); + JITSymbol Symbol = T2.findSymbol(Name, ExportedOnly); + M.verifyFindSymbol(Symbol); + + // Test findSymbolIn + Name = "bar"; + ExportedOnly = false; + M.expectFindSymbolIn(H, Name, ExportedOnly); + Symbol = T1.findSymbolIn(H, Name, ExportedOnly); + M.verifyFindSymbolIn(Symbol); + + // Test emitAndFinalize + M.expectEmitAndFinalize(H); + T2.emitAndFinalize(H); + M.verifyEmitAndFinalize(); + + // Test mapSectionAddress + char Buffer[24]; + TargetAddress MockAddress = 255; + M.expectMapSectionAddress(H, Buffer, MockAddress); + T1.mapSectionAddress(H, Buffer, MockAddress); + M.verifyMapSectionAddress(); + + // Verify transform getter (non-const) + MockObjectFile Mutatee = 277; + MockObjectFile *Out = T2.getTransform()(&Mutatee); + EXPECT_EQ(&Mutatee, Out) << "Expected in-place transform"; + EXPECT_EQ(278, Mutatee) << "Expected incrementing transform"; + + // Verify transform getter (const) + auto OwnedObj = llvm::make_unique<MockObjectFile>(288); + const auto &T1C = T1; + OwnedObj = T1C.getTransform()(std::move(OwnedObj)); + EXPECT_EQ(289, *OwnedObj) << "Expected incrementing transform"; +} +} diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp b/gnu/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp new file mode 100644 index 00000000000..776d26970a3 --- /dev/null +++ b/gnu/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp @@ -0,0 +1,160 @@ +//===--------------- OrcCAPITest.cpp - Unit tests Orc C API ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "OrcTestCommon.h" +#include "gtest/gtest.h" +#include "llvm-c/Core.h" +#include "llvm-c/OrcBindings.h" +#include "llvm-c/Target.h" +#include "llvm-c/TargetMachine.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +namespace llvm { + +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef) + +class OrcCAPIExecutionTest : public testing::Test, public OrcExecutionTest { +protected: + std::unique_ptr<Module> createTestModule(const Triple &TT) { + ModuleBuilder MB(getGlobalContext(), TT.str(), ""); + Function *TestFunc = MB.createFunctionDecl<int()>("testFunc"); + Function *Main = MB.createFunctionDecl<int(int, char*[])>("main"); + + Main->getBasicBlockList().push_back(BasicBlock::Create(getGlobalContext())); + IRBuilder<> B(&Main->back()); + Value* Result = B.CreateCall(TestFunc); + B.CreateRet(Result); + + return MB.takeModule(); + } + + typedef int (*MainFnTy)(); + + static int myTestFuncImpl() { + return 42; + } + + static char *testFuncName; + + static uint64_t myResolver(const char *Name, void *Ctx) { + if (!strncmp(Name, testFuncName, 8)) + return (uint64_t)&myTestFuncImpl; + return 0; + } + + struct CompileContext { + CompileContext() : Compiled(false) { } + + OrcCAPIExecutionTest* APIExecTest; + std::unique_ptr<Module> M; + LLVMOrcModuleHandle H; + bool Compiled; + }; + + static LLVMOrcTargetAddress myCompileCallback(LLVMOrcJITStackRef JITStack, + void *Ctx) { + CompileContext *CCtx = static_cast<CompileContext*>(Ctx); + auto *ET = CCtx->APIExecTest; + CCtx->M = ET->createTestModule(ET->TM->getTargetTriple()); + CCtx->H = LLVMOrcAddEagerlyCompiledIR(JITStack, wrap(CCtx->M.get()), + myResolver, nullptr); + CCtx->Compiled = true; + LLVMOrcTargetAddress MainAddr = LLVMOrcGetSymbolAddress(JITStack, "main"); + LLVMOrcSetIndirectStubPointer(JITStack, "foo", MainAddr); + return MainAddr; + } +}; + +char *OrcCAPIExecutionTest::testFuncName = nullptr; + +TEST_F(OrcCAPIExecutionTest, TestEagerIRCompilation) { + if (!TM) + return; + + LLVMOrcJITStackRef JIT = + LLVMOrcCreateInstance(wrap(TM.get())); + + std::unique_ptr<Module> M = createTestModule(TM->getTargetTriple()); + + LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc"); + + LLVMOrcModuleHandle H = + LLVMOrcAddEagerlyCompiledIR(JIT, wrap(M.get()), myResolver, nullptr); + MainFnTy MainFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "main"); + int Result = MainFn(); + EXPECT_EQ(Result, 42) + << "Eagerly JIT'd code did not return expected result"; + + LLVMOrcRemoveModule(JIT, H); + + LLVMOrcDisposeMangledSymbol(testFuncName); + LLVMOrcDisposeInstance(JIT); +} + +TEST_F(OrcCAPIExecutionTest, TestLazyIRCompilation) { + if (!TM) + return; + + LLVMOrcJITStackRef JIT = + LLVMOrcCreateInstance(wrap(TM.get())); + + std::unique_ptr<Module> M = createTestModule(TM->getTargetTriple()); + + LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc"); + + LLVMOrcModuleHandle H = + LLVMOrcAddLazilyCompiledIR(JIT, wrap(M.get()), myResolver, nullptr); + MainFnTy MainFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "main"); + 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; + + LLVMOrcJITStackRef JIT = + LLVMOrcCreateInstance(wrap(TM.get())); + + LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc"); + + CompileContext C; + C.APIExecTest = this; + LLVMOrcCreateIndirectStub(JIT, "foo", + LLVMOrcCreateLazyCompileCallback(JIT, + myCompileCallback, + &C)); + MainFnTy FooFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "foo"); + int Result = FooFn(); + EXPECT_TRUE(C.Compiled) + << "Function wasn't lazily compiled"; + EXPECT_EQ(Result, 42) + << "Direct-callback JIT'd code did not return expected result"; + + C.Compiled = false; + FooFn(); + EXPECT_FALSE(C.Compiled) + << "Direct-callback JIT'd code was JIT'd twice"; + + LLVMOrcRemoveModule(JIT, C.H); + + LLVMOrcDisposeMangledSymbol(testFuncName); + LLVMOrcDisposeInstance(JIT); +} + +} // namespace llvm diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp b/gnu/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp new file mode 100644 index 00000000000..17d1e9c9276 --- /dev/null +++ b/gnu/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp @@ -0,0 +1,25 @@ +//===--------- OrcTestCommon.cpp - Utilities for Orc Unit Tests -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Common utilities for Orc unit tests. +// +//===----------------------------------------------------------------------===// + +#include "OrcTestCommon.h" + +using namespace llvm; + +bool OrcExecutionTest::NativeTargetInitialized = false; + +ModuleBuilder::ModuleBuilder(LLVMContext &Context, StringRef Triple, + StringRef Name) + : M(new Module(Name, Context)) { + if (Triple != "") + M->setTargetTriple(Triple); +} diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h b/gnu/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h new file mode 100644 index 00000000000..f480e0789ae --- /dev/null +++ b/gnu/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h @@ -0,0 +1,179 @@ +//===------ OrcTestCommon.h - Utilities for Orc Unit Tests ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Common utilities for the Orc unit tests. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_ORC_ORCTESTCOMMON_H +#define LLVM_UNITTESTS_EXECUTIONENGINE_ORC_ORCTESTCOMMON_H + +#include "llvm/IR/Function.h" +#include "llvm/IR/IRBuilder.h" +#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" +#include <memory> + +namespace llvm { + +// Base class for Orc tests that will execute code. +class OrcExecutionTest { +public: + + OrcExecutionTest() { + if (!NativeTargetInitialized) { + InitializeNativeTarget(); + InitializeNativeTargetAsmParser(); + InitializeNativeTargetAsmPrinter(); + NativeTargetInitialized = true; + } + + // Try to select a TargetMachine for the host. + TM.reset(EngineBuilder().selectTarget()); + + if (TM) { + // If we found a TargetMachine, check that it's one that Orc supports. + const Triple& TT = TM->getTargetTriple(); + if (TT.getArch() != Triple::x86_64 || !TT.isOSDarwin()) + TM = nullptr; + } + }; + +protected: + std::unique_ptr<TargetMachine> TM; +private: + static bool NativeTargetInitialized; +}; + +class ModuleBuilder { +public: + ModuleBuilder(LLVMContext &Context, StringRef Triple, + StringRef Name); + + template <typename FuncType> + Function* createFunctionDecl(StringRef Name) { + return Function::Create( + TypeBuilder<FuncType, false>::get(M->getContext()), + GlobalValue::ExternalLinkage, Name, M.get()); + } + + Module* getModule() { return M.get(); } + const Module* getModule() const { return M.get(); } + std::unique_ptr<Module> takeModule() { return std::move(M); } + +private: + std::unique_ptr<Module> M; +}; + +// Dummy struct type. +struct DummyStruct { + int X[256]; +}; + +// TypeBuilder specialization for DummyStruct. +template <bool XCompile> +class TypeBuilder<DummyStruct, XCompile> { +public: + static StructType *get(LLVMContext &Context) { + return StructType::get( + TypeBuilder<types::i<32>[256], XCompile>::get(Context), nullptr); + } +}; + +template <typename HandleT, + typename AddModuleSetFtor, + typename RemoveModuleSetFtor, + typename FindSymbolFtor, + typename FindSymbolInFtor> +class MockBaseLayer { +public: + + typedef HandleT ModuleSetHandleT; + + MockBaseLayer(AddModuleSetFtor &&AddModuleSet, + RemoveModuleSetFtor &&RemoveModuleSet, + FindSymbolFtor &&FindSymbol, + FindSymbolInFtor &&FindSymbolIn) + : AddModuleSet(AddModuleSet), RemoveModuleSet(RemoveModuleSet), + FindSymbol(FindSymbol), FindSymbolIn(FindSymbolIn) + {} + + template <typename ModuleSetT, typename MemoryManagerPtrT, + typename SymbolResolverPtrT> + ModuleSetHandleT addModuleSet(ModuleSetT Ms, MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) { + return AddModuleSet(std::move(Ms), std::move(MemMgr), std::move(Resolver)); + } + + void removeModuleSet(ModuleSetHandleT H) { + RemoveModuleSet(H); + } + + orc::JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { + return FindSymbol(Name, ExportedSymbolsOnly); + } + + orc::JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name, + bool ExportedSymbolsOnly) { + return FindSymbolIn(H, Name, ExportedSymbolsOnly); + } + +private: + AddModuleSetFtor AddModuleSet; + RemoveModuleSetFtor RemoveModuleSet; + FindSymbolFtor FindSymbol; + FindSymbolInFtor FindSymbolIn; +}; + +template <typename ModuleSetHandleT, + typename AddModuleSetFtor, + typename RemoveModuleSetFtor, + typename FindSymbolFtor, + typename FindSymbolInFtor> +MockBaseLayer<ModuleSetHandleT, AddModuleSetFtor, RemoveModuleSetFtor, + FindSymbolFtor, FindSymbolInFtor> +createMockBaseLayer(AddModuleSetFtor &&AddModuleSet, + RemoveModuleSetFtor &&RemoveModuleSet, + FindSymbolFtor &&FindSymbol, + FindSymbolInFtor &&FindSymbolIn) { + return MockBaseLayer<ModuleSetHandleT, AddModuleSetFtor, RemoveModuleSetFtor, + FindSymbolFtor, FindSymbolInFtor>( + std::forward<AddModuleSetFtor>(AddModuleSet), + std::forward<RemoveModuleSetFtor>(RemoveModuleSet), + std::forward<FindSymbolFtor>(FindSymbol), + std::forward<FindSymbolInFtor>(FindSymbolIn)); +} + +template <typename ReturnT> +class DoNothingAndReturn { +public: + DoNothingAndReturn(ReturnT Val) : Val(Val) {} + + template <typename... Args> + ReturnT operator()(Args...) const { return Val; } +private: + ReturnT Val; +}; + +template <> +class DoNothingAndReturn<void> { +public: + template <typename... Args> + void operator()(Args...) const { } +}; + +} // namespace llvm + +#endif diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp b/gnu/llvm/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp new file mode 100644 index 00000000000..8215144a514 --- /dev/null +++ b/gnu/llvm/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"; + } +} |
