[ORC] Rename ORC layers to make the "new" ORC layers the default.
This commit adds a 'Legacy' prefix to old ORC layers and utilities, and removes
the '2' suffix from the new ORC layers. If you wish to continue using the old
ORC layers you will need to add a 'Legacy' prefix to your classes. If you were
already using the new ORC layers you will need to drop the '2' suffix.
The legacy layers will remain in-tree until the new layers reach feature
parity with them. This will involve adding support for removing code from the
new layers, and ensuring that performance is comperable.
llvm-svn: 344572
diff --git a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
index 8b0d5fc..019437d 100644
--- a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
+++ b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
@@ -10,7 +10,6 @@
)
add_llvm_unittest(OrcJITTests
- CompileOnDemandLayerTest.cpp
CoreAPIsTest.cpp
IndirectionUtilsTest.cpp
GlobalMappingLayerTest.cpp
@@ -18,6 +17,8 @@
LazyCallThroughAndReexportsTest.cpp
LazyEmittingLayerTest.cpp
LegacyAPIInteropTest.cpp
+ LegacyCompileOnDemandLayerTest.cpp
+ LegacyRTDyldObjectLinkingLayerTest.cpp
ObjectTransformLayerTest.cpp
OrcCAPITest.cpp
OrcTestCommon.cpp
@@ -25,7 +26,6 @@
RemoteObjectLayerTest.cpp
RPCUtilsTest.cpp
RTDyldObjectLinkingLayerTest.cpp
- RTDyldObjectLinkingLayer2Test.cpp
SymbolStringPoolTest.cpp
ThreadSafeModuleTest.cpp
)
diff --git a/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/LegacyCompileOnDemandLayerTest.cpp
similarity index 95%
rename from llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp
rename to llvm/unittests/ExecutionEngine/Orc/LegacyCompileOnDemandLayerTest.cpp
index 9aa4437..38f7a65 100644
--- a/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/LegacyCompileOnDemandLayerTest.cpp
@@ -54,7 +54,7 @@
}
};
-TEST(CompileOnDemandLayerTest, FindSymbol) {
+TEST(LegacyCompileOnDemandLayerTest, FindSymbol) {
MockBaseLayer<int, std::shared_ptr<Module>> TestBaseLayer;
TestBaseLayer.findSymbolImpl =
[](const std::string &Name, bool) {
@@ -76,7 +76,7 @@
llvm_unreachable("Should never be called");
};
- llvm::orc::CompileOnDemandLayer<decltype(TestBaseLayer)> COD(
+ llvm::orc::LegacyCompileOnDemandLayer<decltype(TestBaseLayer)> COD(
ES, TestBaseLayer, GetResolver, SetResolver,
[](Function &F) { return std::set<Function *>{&F}; }, CallbackMgr,
[] { return llvm::make_unique<DummyStubsManager>(); }, true);
diff --git a/llvm/unittests/ExecutionEngine/Orc/LegacyRTDyldObjectLinkingLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/LegacyRTDyldObjectLinkingLayerTest.cpp
new file mode 100644
index 0000000..8c9c958
--- /dev/null
+++ b/llvm/unittests/ExecutionEngine/Orc/LegacyRTDyldObjectLinkingLayerTest.cpp
@@ -0,0 +1,282 @@
+//===- RTDyldObjectLinkingLayerTest.cpp - RTDyld linking layer unit tests -===//
+//
+// 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/RTDyldObjectLinkingLayer.h"
+#include "OrcTestCommon.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
+#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
+#include "llvm/ExecutionEngine/Orc/Legacy.h"
+#include "llvm/ExecutionEngine/Orc/NullResolver.h"
+#include "llvm/ExecutionEngine/SectionMemoryManager.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/LLVMContext.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::orc;
+
+namespace {
+
+class LegacyRTDyldObjectLinkingLayerExecutionTest : public testing::Test,
+ public OrcExecutionTest {
+
+};
+
+class SectionMemoryManagerWrapper : public SectionMemoryManager {
+public:
+ int FinalizationCount = 0;
+ int NeedsToReserveAllocationSpaceCount = 0;
+
+ bool needsToReserveAllocationSpace() override {
+ ++NeedsToReserveAllocationSpaceCount;
+ return SectionMemoryManager::needsToReserveAllocationSpace();
+ }
+
+ bool finalizeMemory(std::string *ErrMsg = nullptr) override {
+ ++FinalizationCount;
+ return SectionMemoryManager::finalizeMemory(ErrMsg);
+ }
+};
+
+TEST(LegacyRTDyldObjectLinkingLayerTest, TestSetProcessAllSections) {
+ class MemoryManagerWrapper : public SectionMemoryManager {
+ public:
+ MemoryManagerWrapper(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;
+ };
+
+ bool DebugSectionSeen = false;
+ auto MM = std::make_shared<MemoryManagerWrapper>(DebugSectionSeen);
+
+ ExecutionSession ES;
+
+ LegacyRTDyldObjectLinkingLayer ObjLayer(ES, [&MM](VModuleKey) {
+ return LegacyRTDyldObjectLinkingLayer::Resources{
+ MM, std::make_shared<NullResolver>()};
+ });
+
+ LLVMContext Context;
+ auto M = llvm::make_unique<Module>("", Context);
+ M->setTargetTriple("x86_64-unknown-linux-gnu");
+ Type *Int32Ty = IntegerType::get(Context, 32);
+ GlobalVariable *GV =
+ new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage,
+ ConstantInt::get(Int32Ty, 42), "foo");
+
+ GV->setSection(".debug_str");
+
+
+ // Initialize the native target in case this is the first unit test
+ // to try to build a TM.
+ OrcNativeTarget::initialize();
+ std::unique_ptr<TargetMachine> TM(
+ EngineBuilder().selectTarget(Triple(M->getTargetTriple()), "", "",
+ SmallVector<std::string, 1>()));
+ if (!TM)
+ return;
+
+ auto Obj = SimpleCompiler(*TM)(*M);
+
+ {
+ // Test with ProcessAllSections = false (the default).
+ auto K = ES.allocateVModule();
+ cantFail(ObjLayer.addObject(
+ K, MemoryBuffer::getMemBufferCopy(Obj->getBuffer())));
+ cantFail(ObjLayer.emitAndFinalize(K));
+ EXPECT_EQ(DebugSectionSeen, false)
+ << "Unexpected debug info section";
+ cantFail(ObjLayer.removeObject(K));
+ }
+
+ {
+ // Test with ProcessAllSections = true.
+ ObjLayer.setProcessAllSections(true);
+ auto K = ES.allocateVModule();
+ cantFail(ObjLayer.addObject(K, std::move(Obj)));
+ cantFail(ObjLayer.emitAndFinalize(K));
+ EXPECT_EQ(DebugSectionSeen, true)
+ << "Expected debug info section not seen";
+ cantFail(ObjLayer.removeObject(K));
+ }
+}
+
+TEST_F(LegacyRTDyldObjectLinkingLayerExecutionTest, NoDuplicateFinalization) {
+ if (!SupportsJIT)
+ return;
+
+ ExecutionSession ES;
+
+ auto MM = std::make_shared<SectionMemoryManagerWrapper>();
+
+ std::map<orc::VModuleKey, std::shared_ptr<orc::SymbolResolver>> Resolvers;
+
+ LegacyRTDyldObjectLinkingLayer ObjLayer(ES, [&](VModuleKey K) {
+ auto I = Resolvers.find(K);
+ assert(I != Resolvers.end() && "Missing resolver");
+ auto R = std::move(I->second);
+ Resolvers.erase(I);
+ return LegacyRTDyldObjectLinkingLayer::Resources{MM, std::move(R)};
+ });
+ 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(); }
+ //
+ // Verify that the memory manager is only finalized once (for Module 2).
+ // Failure suggests that finalize is being called on the inner RTDyld
+ // instance (for Module 1) which is unsafe, as it will prevent relocation of
+ // Module 2.
+
+ ModuleBuilder MB1(Context, "", "dummy");
+ {
+ MB1.getModule()->setDataLayout(TM->createDataLayout());
+ Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("bar");
+ BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
+ IRBuilder<> Builder(BarEntry);
+ IntegerType *Int32Ty = IntegerType::get(Context, 32);
+ Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
+ Builder.CreateRet(FourtyTwo);
+ }
+
+ auto Obj1 = Compile(*MB1.getModule());
+
+ ModuleBuilder MB2(Context, "", "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(Context, "entry", FooImpl);
+ IRBuilder<> Builder(FooEntry);
+ Builder.CreateRet(Builder.CreateCall(BarDecl));
+ }
+ auto Obj2 = Compile(*MB2.getModule());
+
+ auto K1 = ES.allocateVModule();
+ Resolvers[K1] = std::make_shared<NullResolver>();
+ cantFail(ObjLayer.addObject(K1, std::move(Obj1)));
+
+ auto K2 = ES.allocateVModule();
+ auto LegacyLookup = [&](const std::string &Name) {
+ return ObjLayer.findSymbol(Name, true);
+ };
+
+ Resolvers[K2] = createSymbolResolver(
+ [&](const SymbolNameSet &Symbols) {
+ return cantFail(
+ getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup));
+ },
+ [&](std::shared_ptr<AsynchronousSymbolQuery> Query,
+ const SymbolNameSet &Symbols) {
+ return lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
+ });
+
+ cantFail(ObjLayer.addObject(K2, std::move(Obj2)));
+ cantFail(ObjLayer.emitAndFinalize(K2));
+ cantFail(ObjLayer.removeObject(K2));
+
+ // Finalization of module 2 should trigger finalization of module 1.
+ // Verify that finalize on SMMW is only called once.
+ EXPECT_EQ(MM->FinalizationCount, 1)
+ << "Extra call to finalize";
+}
+
+TEST_F(LegacyRTDyldObjectLinkingLayerExecutionTest, NoPrematureAllocation) {
+ if (!SupportsJIT)
+ return;
+
+ ExecutionSession ES;
+
+ auto MM = std::make_shared<SectionMemoryManagerWrapper>();
+
+ LegacyRTDyldObjectLinkingLayer ObjLayer(ES, [&MM](VModuleKey K) {
+ return LegacyRTDyldObjectLinkingLayer::Resources{
+ MM, std::make_shared<NullResolver>()};
+ });
+ SimpleCompiler Compile(*TM);
+
+ // Create a pair of unrelated modules:
+ //
+ // Module 1:
+ // int foo() { return 42; }
+ // Module 2:
+ // int bar() { return 7; }
+ //
+ // Both modules will share a memory manager. We want to verify that the
+ // second object is not loaded before the first one is finalized. To do this
+ // in a portable way, we abuse the
+ // RuntimeDyld::MemoryManager::needsToReserveAllocationSpace hook, which is
+ // called once per object before any sections are allocated.
+
+ ModuleBuilder MB1(Context, "", "dummy");
+ {
+ MB1.getModule()->setDataLayout(TM->createDataLayout());
+ Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("foo");
+ BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
+ IRBuilder<> Builder(BarEntry);
+ IntegerType *Int32Ty = IntegerType::get(Context, 32);
+ Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
+ Builder.CreateRet(FourtyTwo);
+ }
+
+ auto Obj1 = Compile(*MB1.getModule());
+
+ ModuleBuilder MB2(Context, "", "dummy");
+ {
+ MB2.getModule()->setDataLayout(TM->createDataLayout());
+ Function *BarImpl = MB2.createFunctionDecl<int32_t(void)>("bar");
+ BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
+ IRBuilder<> Builder(BarEntry);
+ IntegerType *Int32Ty = IntegerType::get(Context, 32);
+ Value *Seven = ConstantInt::getSigned(Int32Ty, 7);
+ Builder.CreateRet(Seven);
+ }
+ auto Obj2 = Compile(*MB2.getModule());
+
+ auto K = ES.allocateVModule();
+ cantFail(ObjLayer.addObject(K, std::move(Obj1)));
+ cantFail(ObjLayer.addObject(ES.allocateVModule(), std::move(Obj2)));
+ cantFail(ObjLayer.emitAndFinalize(K));
+ cantFail(ObjLayer.removeObject(K));
+
+ // Only one call to needsToReserveAllocationSpace should have been made.
+ EXPECT_EQ(MM->NeedsToReserveAllocationSpaceCount, 1)
+ << "More than one call to needsToReserveAllocationSpace "
+ "(multiple unrelated objects loaded prior to finalization)";
+}
+
+TEST_F(LegacyRTDyldObjectLinkingLayerExecutionTest, TestNotifyLoadedSignature) {
+ ExecutionSession ES;
+ LegacyRTDyldObjectLinkingLayer ObjLayer(
+ ES,
+ [](VModuleKey) {
+ return LegacyRTDyldObjectLinkingLayer::Resources{
+ nullptr, std::make_shared<NullResolver>()};
+ },
+ [](VModuleKey, const object::ObjectFile &obj,
+ const RuntimeDyld::LoadedObjectInfo &info) {});
+}
+
+} // end anonymous namespace
diff --git a/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp
index 6ad3c19..1c53024 100644
--- a/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp
@@ -175,19 +175,19 @@
}
};
-// Test each operation on ObjectTransformLayer.
-TEST(ObjectTransformLayerTest, Main) {
+// Test each operation on LegacyObjectTransformLayer.
+TEST(LegacyObjectTransformLayerTest, Main) {
MockBaseLayer M;
ExecutionSession ES(std::make_shared<SymbolStringPool>());
// 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);
+ LegacyObjectTransformLayer<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,
+ LegacyObjectTransformLayer<MockBaseLayer,
std::function<std::shared_ptr<MockObjectFile>(
std::shared_ptr<MockObjectFile>)>>
T2(M, [](std::shared_ptr<MockObjectFile> Obj) {
@@ -257,9 +257,9 @@
if (!RunStaticChecks)
return;
- // Make sure that ObjectTransformLayer implements the object layer concept
+ // Make sure that LegacyObjectTransformLayer implements the object layer concept
// correctly by sandwitching one between an ObjectLinkingLayer and an
- // IRCompileLayer, verifying that it compiles if we have a call to the
+ // LegacyIRCompileLayer, verifying that it compiles if we have a call to the
// IRComileLayer's addModule that should call the transform layer's
// addObject, and also calling the other public transform layer methods
// directly to make sure the methods they intend to forward to exist on
@@ -282,8 +282,8 @@
};
// Construct the jit layers.
- RTDyldObjectLinkingLayer BaseLayer(ES, [](VModuleKey) {
- return RTDyldObjectLinkingLayer::Resources{
+ LegacyRTDyldObjectLinkingLayer BaseLayer(ES, [](VModuleKey) {
+ return LegacyRTDyldObjectLinkingLayer::Resources{
std::make_shared<llvm::SectionMemoryManager>(),
std::make_shared<NullResolver>()};
});
@@ -291,20 +291,20 @@
auto IdentityTransform = [](std::unique_ptr<llvm::MemoryBuffer> Obj) {
return Obj;
};
- ObjectTransformLayer<decltype(BaseLayer), decltype(IdentityTransform)>
+ LegacyObjectTransformLayer<decltype(BaseLayer), decltype(IdentityTransform)>
TransformLayer(BaseLayer, IdentityTransform);
auto NullCompiler = [](llvm::Module &) {
return std::unique_ptr<llvm::MemoryBuffer>(nullptr);
};
- IRCompileLayer<decltype(TransformLayer), decltype(NullCompiler)>
+ LegacyIRCompileLayer<decltype(TransformLayer), decltype(NullCompiler)>
CompileLayer(TransformLayer, NullCompiler);
- // Make sure that the calls from IRCompileLayer to ObjectTransformLayer
+ // Make sure that the calls from LegacyIRCompileLayer to LegacyObjectTransformLayer
// compile.
cantFail(CompileLayer.addModule(ES.allocateVModule(),
std::unique_ptr<llvm::Module>()));
- // Make sure that the calls from ObjectTransformLayer to ObjectLinkingLayer
+ // Make sure that the calls from LegacyObjectTransformLayer to ObjectLinkingLayer
// compile.
VModuleKey DummyKey = ES.allocateVModule();
cantFail(TransformLayer.emitAndFinalize(DummyKey));
diff --git a/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayer2Test.cpp b/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayer2Test.cpp
deleted file mode 100644
index 1dbd48b..0000000
--- a/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayer2Test.cpp
+++ /dev/null
@@ -1,228 +0,0 @@
-//===--- RTDyldObjectLinkingLayer2Test.cpp - RTDyld linking layer tests ---===//
-//
-// 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/Orc/CompileUtils.h"
-#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
-#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
-#include "llvm/ExecutionEngine/Orc/Legacy.h"
-#include "llvm/ExecutionEngine/Orc/NullResolver.h"
-#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
-#include "llvm/ExecutionEngine/SectionMemoryManager.h"
-#include "llvm/IR/Constants.h"
-#include "llvm/IR/LLVMContext.h"
-#include "gtest/gtest.h"
-
-using namespace llvm;
-using namespace llvm::orc;
-
-namespace {
-
-class RTDyldObjectLinkingLayer2ExecutionTest : public testing::Test,
- public OrcExecutionTest {};
-
-// Adds an object with a debug section to RuntimeDyld and then returns whether
-// the debug section was passed to the memory manager.
-static bool testSetProcessAllSections(std::unique_ptr<MemoryBuffer> Obj,
- bool ProcessAllSections) {
- class MemoryManagerWrapper : public SectionMemoryManager {
- public:
- MemoryManagerWrapper(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;
- };
-
- bool DebugSectionSeen = false;
-
- ExecutionSession ES;
- auto &JD = ES.createJITDylib("main");
- auto Foo = ES.intern("foo");
-
- RTDyldObjectLinkingLayer2 ObjLayer(ES, [&DebugSectionSeen](VModuleKey) {
- return llvm::make_unique<MemoryManagerWrapper>(DebugSectionSeen);
- });
-
- auto OnResolveDoNothing = [](Expected<SymbolMap> R) {
- cantFail(std::move(R));
- };
-
- auto OnReadyDoNothing = [](Error Err) { cantFail(std::move(Err)); };
-
- ObjLayer.setProcessAllSections(ProcessAllSections);
- auto K = ES.allocateVModule();
- cantFail(ObjLayer.add(JD, K, std::move(Obj)));
- ES.lookup({&JD}, {Foo}, OnResolveDoNothing, OnReadyDoNothing,
- NoDependenciesToRegister);
- return DebugSectionSeen;
-}
-
-TEST(RTDyldObjectLinkingLayer2Test, TestSetProcessAllSections) {
- LLVMContext Context;
- auto M = llvm::make_unique<Module>("", Context);
- M->setTargetTriple("x86_64-unknown-linux-gnu");
- Type *Int32Ty = IntegerType::get(Context, 32);
- GlobalVariable *GV =
- new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage,
- ConstantInt::get(Int32Ty, 42), "foo");
-
- GV->setSection(".debug_str");
-
- // Initialize the native target in case this is the first unit test
- // to try to build a TM.
- OrcNativeTarget::initialize();
- std::unique_ptr<TargetMachine> TM(EngineBuilder().selectTarget(
- Triple(M->getTargetTriple()), "", "", SmallVector<std::string, 1>()));
- if (!TM)
- return;
-
- auto Obj = SimpleCompiler(*TM)(*M);
-
- EXPECT_FALSE(testSetProcessAllSections(
- MemoryBuffer::getMemBufferCopy(Obj->getBuffer()), false))
- << "Debug section seen despite ProcessAllSections being false";
- EXPECT_TRUE(testSetProcessAllSections(std::move(Obj), true))
- << "Expected to see debug section when ProcessAllSections is true";
-}
-
-TEST(RTDyldObjectLinkingLayer2Test, TestOverrideObjectFlags) {
-
- OrcNativeTarget::initialize();
-
- std::unique_ptr<TargetMachine> TM(
- EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "",
- SmallVector<std::string, 1>()));
-
- if (!TM)
- return;
-
- // Our compiler is going to modify symbol visibility settings without telling
- // ORC. This will test our ability to override the flags later.
- class FunkySimpleCompiler : public SimpleCompiler {
- public:
- FunkySimpleCompiler(TargetMachine &TM) : SimpleCompiler(TM) {}
-
- CompileResult operator()(Module &M) {
- auto *Foo = M.getFunction("foo");
- assert(Foo && "Expected function Foo not found");
- Foo->setVisibility(GlobalValue::HiddenVisibility);
- return SimpleCompiler::operator()(M);
- }
- };
-
- // Create a module with two void() functions: foo and bar.
- ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>());
- ThreadSafeModule M;
- {
- ModuleBuilder MB(*TSCtx.getContext(), TM->getTargetTriple().str(), "dummy");
- MB.getModule()->setDataLayout(TM->createDataLayout());
-
- Function *FooImpl = MB.createFunctionDecl<void()>("foo");
- BasicBlock *FooEntry =
- BasicBlock::Create(*TSCtx.getContext(), "entry", FooImpl);
- IRBuilder<> B1(FooEntry);
- B1.CreateRetVoid();
-
- Function *BarImpl = MB.createFunctionDecl<void()>("bar");
- BasicBlock *BarEntry =
- BasicBlock::Create(*TSCtx.getContext(), "entry", BarImpl);
- IRBuilder<> B2(BarEntry);
- B2.CreateRetVoid();
-
- M = ThreadSafeModule(MB.takeModule(), std::move(TSCtx));
- }
-
- // Create a simple stack and set the override flags option.
- ExecutionSession ES;
- auto &JD = ES.createJITDylib("main");
- auto Foo = ES.intern("foo");
- RTDyldObjectLinkingLayer2 ObjLayer(
- ES, [](VModuleKey) { return llvm::make_unique<SectionMemoryManager>(); });
- IRCompileLayer2 CompileLayer(ES, ObjLayer, FunkySimpleCompiler(*TM));
-
- ObjLayer.setOverrideObjectFlagsWithResponsibilityFlags(true);
-
- cantFail(CompileLayer.add(JD, ES.allocateVModule(), std::move(M)));
- ES.lookup({&JD}, {Foo}, [](Expected<SymbolMap> R) { cantFail(std::move(R)); },
- [](Error Err) { cantFail(std::move(Err)); },
- NoDependenciesToRegister);
-}
-
-TEST(RTDyldObjectLinkingLayer2Test, TestAutoClaimResponsibilityForSymbols) {
-
- OrcNativeTarget::initialize();
-
- std::unique_ptr<TargetMachine> TM(
- EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "",
- SmallVector<std::string, 1>()));
-
- if (!TM)
- return;
-
- // Our compiler is going to add a new symbol without telling ORC.
- // This will test our ability to auto-claim responsibility later.
- class FunkySimpleCompiler : public SimpleCompiler {
- public:
- FunkySimpleCompiler(TargetMachine &TM) : SimpleCompiler(TM) {}
-
- CompileResult operator()(Module &M) {
- Function *BarImpl =
- Function::Create(TypeBuilder<void(), false>::get(M.getContext()),
- GlobalValue::ExternalLinkage, "bar", &M);
- BasicBlock *BarEntry =
- BasicBlock::Create(M.getContext(), "entry", BarImpl);
- IRBuilder<> B(BarEntry);
- B.CreateRetVoid();
-
- return SimpleCompiler::operator()(M);
- }
- };
-
- // Create a module with two void() functions: foo and bar.
- ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>());
- ThreadSafeModule M;
- {
- ModuleBuilder MB(*TSCtx.getContext(), TM->getTargetTriple().str(), "dummy");
- MB.getModule()->setDataLayout(TM->createDataLayout());
-
- Function *FooImpl = MB.createFunctionDecl<void()>("foo");
- BasicBlock *FooEntry =
- BasicBlock::Create(*TSCtx.getContext(), "entry", FooImpl);
- IRBuilder<> B(FooEntry);
- B.CreateRetVoid();
-
- M = ThreadSafeModule(MB.takeModule(), std::move(TSCtx));
- }
-
- // Create a simple stack and set the override flags option.
- ExecutionSession ES;
- auto &JD = ES.createJITDylib("main");
- auto Foo = ES.intern("foo");
- RTDyldObjectLinkingLayer2 ObjLayer(
- ES, [](VModuleKey) { return llvm::make_unique<SectionMemoryManager>(); });
- IRCompileLayer2 CompileLayer(ES, ObjLayer, FunkySimpleCompiler(*TM));
-
- ObjLayer.setAutoClaimResponsibilityForObjectSymbols(true);
-
- cantFail(CompileLayer.add(JD, ES.allocateVModule(), std::move(M)));
- ES.lookup({&JD}, {Foo}, [](Expected<SymbolMap> R) { cantFail(std::move(R)); },
- [](Error Err) { cantFail(std::move(Err)); },
- NoDependenciesToRegister);
-}
-
-} // end anonymous namespace
diff --git a/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp
index 62c6b7d..75ccfc9 100644
--- a/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp
@@ -1,4 +1,4 @@
-//===- RTDyldObjectLinkingLayerTest.cpp - RTDyld linking layer unit tests -===//
+//===--- RTDyldObjectLinkingLayerTest.cpp - RTDyld linking layer tests ---===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,13 +7,14 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
#include "OrcTestCommon.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
+#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
#include "llvm/ExecutionEngine/Orc/Legacy.h"
#include "llvm/ExecutionEngine/Orc/NullResolver.h"
+#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/LLVMContext.h"
@@ -25,258 +26,203 @@
namespace {
class RTDyldObjectLinkingLayerExecutionTest : public testing::Test,
- public OrcExecutionTest {
+ public OrcExecutionTest {};
-};
-
-class SectionMemoryManagerWrapper : public SectionMemoryManager {
-public:
- int FinalizationCount = 0;
- int NeedsToReserveAllocationSpaceCount = 0;
-
- bool needsToReserveAllocationSpace() override {
- ++NeedsToReserveAllocationSpaceCount;
- return SectionMemoryManager::needsToReserveAllocationSpace();
- }
-
- bool finalizeMemory(std::string *ErrMsg = nullptr) override {
- ++FinalizationCount;
- return SectionMemoryManager::finalizeMemory(ErrMsg);
- }
-};
-
-TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) {
+// Adds an object with a debug section to RuntimeDyld and then returns whether
+// the debug section was passed to the memory manager.
+static bool testSetProcessAllSections(std::unique_ptr<MemoryBuffer> Obj,
+ bool ProcessAllSections) {
class MemoryManagerWrapper : public SectionMemoryManager {
public:
MemoryManagerWrapper(bool &DebugSeen) : DebugSeen(DebugSeen) {}
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
- unsigned SectionID,
- StringRef SectionName,
+ unsigned SectionID, StringRef SectionName,
bool IsReadOnly) override {
if (SectionName == ".debug_str")
DebugSeen = true;
- return SectionMemoryManager::allocateDataSection(Size, Alignment,
- SectionID,
- SectionName,
- IsReadOnly);
+ return SectionMemoryManager::allocateDataSection(
+ Size, Alignment, SectionID, SectionName, IsReadOnly);
}
+
private:
bool &DebugSeen;
};
bool DebugSectionSeen = false;
- auto MM = std::make_shared<MemoryManagerWrapper>(DebugSectionSeen);
ExecutionSession ES;
+ auto &JD = ES.createJITDylib("main");
+ auto Foo = ES.intern("foo");
- RTDyldObjectLinkingLayer ObjLayer(ES, [&MM](VModuleKey) {
- return RTDyldObjectLinkingLayer::Resources{
- MM, std::make_shared<NullResolver>()};
+ RTDyldObjectLinkingLayer ObjLayer(ES, [&DebugSectionSeen](VModuleKey) {
+ return llvm::make_unique<MemoryManagerWrapper>(DebugSectionSeen);
});
+ auto OnResolveDoNothing = [](Expected<SymbolMap> R) {
+ cantFail(std::move(R));
+ };
+
+ auto OnReadyDoNothing = [](Error Err) { cantFail(std::move(Err)); };
+
+ ObjLayer.setProcessAllSections(ProcessAllSections);
+ auto K = ES.allocateVModule();
+ cantFail(ObjLayer.add(JD, K, std::move(Obj)));
+ ES.lookup({&JD}, {Foo}, OnResolveDoNothing, OnReadyDoNothing,
+ NoDependenciesToRegister);
+ return DebugSectionSeen;
+}
+
+TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) {
LLVMContext Context;
auto M = llvm::make_unique<Module>("", Context);
M->setTargetTriple("x86_64-unknown-linux-gnu");
Type *Int32Ty = IntegerType::get(Context, 32);
GlobalVariable *GV =
- new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage,
+ new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage,
ConstantInt::get(Int32Ty, 42), "foo");
GV->setSection(".debug_str");
-
// Initialize the native target in case this is the first unit test
// to try to build a TM.
OrcNativeTarget::initialize();
- std::unique_ptr<TargetMachine> TM(
- EngineBuilder().selectTarget(Triple(M->getTargetTriple()), "", "",
- SmallVector<std::string, 1>()));
+ std::unique_ptr<TargetMachine> TM(EngineBuilder().selectTarget(
+ Triple(M->getTargetTriple()), "", "", SmallVector<std::string, 1>()));
if (!TM)
return;
auto Obj = SimpleCompiler(*TM)(*M);
- {
- // Test with ProcessAllSections = false (the default).
- auto K = ES.allocateVModule();
- cantFail(ObjLayer.addObject(
- K, MemoryBuffer::getMemBufferCopy(Obj->getBuffer())));
- cantFail(ObjLayer.emitAndFinalize(K));
- EXPECT_EQ(DebugSectionSeen, false)
- << "Unexpected debug info section";
- cantFail(ObjLayer.removeObject(K));
- }
-
- {
- // Test with ProcessAllSections = true.
- ObjLayer.setProcessAllSections(true);
- auto K = ES.allocateVModule();
- cantFail(ObjLayer.addObject(K, std::move(Obj)));
- cantFail(ObjLayer.emitAndFinalize(K));
- EXPECT_EQ(DebugSectionSeen, true)
- << "Expected debug info section not seen";
- cantFail(ObjLayer.removeObject(K));
- }
+ EXPECT_FALSE(testSetProcessAllSections(
+ MemoryBuffer::getMemBufferCopy(Obj->getBuffer()), false))
+ << "Debug section seen despite ProcessAllSections being false";
+ EXPECT_TRUE(testSetProcessAllSections(std::move(Obj), true))
+ << "Expected to see debug section when ProcessAllSections is true";
}
-TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoDuplicateFinalization) {
- if (!SupportsJIT)
+TEST(RTDyldObjectLinkingLayerTest, TestOverrideObjectFlags) {
+
+ OrcNativeTarget::initialize();
+
+ std::unique_ptr<TargetMachine> TM(
+ EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "",
+ SmallVector<std::string, 1>()));
+
+ if (!TM)
return;
- ExecutionSession ES;
+ // Our compiler is going to modify symbol visibility settings without telling
+ // ORC. This will test our ability to override the flags later.
+ class FunkySimpleCompiler : public SimpleCompiler {
+ public:
+ FunkySimpleCompiler(TargetMachine &TM) : SimpleCompiler(TM) {}
- auto MM = std::make_shared<SectionMemoryManagerWrapper>();
-
- std::map<orc::VModuleKey, std::shared_ptr<orc::SymbolResolver>> Resolvers;
-
- RTDyldObjectLinkingLayer ObjLayer(ES, [&](VModuleKey K) {
- auto I = Resolvers.find(K);
- assert(I != Resolvers.end() && "Missing resolver");
- auto R = std::move(I->second);
- Resolvers.erase(I);
- return RTDyldObjectLinkingLayer::Resources{MM, std::move(R)};
- });
- 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(); }
- //
- // Verify that the memory manager is only finalized once (for Module 2).
- // Failure suggests that finalize is being called on the inner RTDyld
- // instance (for Module 1) which is unsafe, as it will prevent relocation of
- // Module 2.
-
- ModuleBuilder MB1(Context, "", "dummy");
- {
- MB1.getModule()->setDataLayout(TM->createDataLayout());
- Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("bar");
- BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
- IRBuilder<> Builder(BarEntry);
- IntegerType *Int32Ty = IntegerType::get(Context, 32);
- Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
- Builder.CreateRet(FourtyTwo);
- }
-
- auto Obj1 = Compile(*MB1.getModule());
-
- ModuleBuilder MB2(Context, "", "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(Context, "entry", FooImpl);
- IRBuilder<> Builder(FooEntry);
- Builder.CreateRet(Builder.CreateCall(BarDecl));
- }
- auto Obj2 = Compile(*MB2.getModule());
-
- auto K1 = ES.allocateVModule();
- Resolvers[K1] = std::make_shared<NullResolver>();
- cantFail(ObjLayer.addObject(K1, std::move(Obj1)));
-
- auto K2 = ES.allocateVModule();
- auto LegacyLookup = [&](const std::string &Name) {
- return ObjLayer.findSymbol(Name, true);
+ CompileResult operator()(Module &M) {
+ auto *Foo = M.getFunction("foo");
+ assert(Foo && "Expected function Foo not found");
+ Foo->setVisibility(GlobalValue::HiddenVisibility);
+ return SimpleCompiler::operator()(M);
+ }
};
- Resolvers[K2] = createSymbolResolver(
- [&](const SymbolNameSet &Symbols) {
- return cantFail(
- getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup));
- },
- [&](std::shared_ptr<AsynchronousSymbolQuery> Query,
- const SymbolNameSet &Symbols) {
- return lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
- });
+ // Create a module with two void() functions: foo and bar.
+ ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>());
+ ThreadSafeModule M;
+ {
+ ModuleBuilder MB(*TSCtx.getContext(), TM->getTargetTriple().str(), "dummy");
+ MB.getModule()->setDataLayout(TM->createDataLayout());
- cantFail(ObjLayer.addObject(K2, std::move(Obj2)));
- cantFail(ObjLayer.emitAndFinalize(K2));
- cantFail(ObjLayer.removeObject(K2));
+ Function *FooImpl = MB.createFunctionDecl<void()>("foo");
+ BasicBlock *FooEntry =
+ BasicBlock::Create(*TSCtx.getContext(), "entry", FooImpl);
+ IRBuilder<> B1(FooEntry);
+ B1.CreateRetVoid();
- // Finalization of module 2 should trigger finalization of module 1.
- // Verify that finalize on SMMW is only called once.
- EXPECT_EQ(MM->FinalizationCount, 1)
- << "Extra call to finalize";
+ Function *BarImpl = MB.createFunctionDecl<void()>("bar");
+ BasicBlock *BarEntry =
+ BasicBlock::Create(*TSCtx.getContext(), "entry", BarImpl);
+ IRBuilder<> B2(BarEntry);
+ B2.CreateRetVoid();
+
+ M = ThreadSafeModule(MB.takeModule(), std::move(TSCtx));
+ }
+
+ // Create a simple stack and set the override flags option.
+ ExecutionSession ES;
+ auto &JD = ES.createJITDylib("main");
+ auto Foo = ES.intern("foo");
+ RTDyldObjectLinkingLayer ObjLayer(
+ ES, [](VModuleKey) { return llvm::make_unique<SectionMemoryManager>(); });
+ IRCompileLayer CompileLayer(ES, ObjLayer, FunkySimpleCompiler(*TM));
+
+ ObjLayer.setOverrideObjectFlagsWithResponsibilityFlags(true);
+
+ cantFail(CompileLayer.add(JD, ES.allocateVModule(), std::move(M)));
+ ES.lookup({&JD}, {Foo}, [](Expected<SymbolMap> R) { cantFail(std::move(R)); },
+ [](Error Err) { cantFail(std::move(Err)); },
+ NoDependenciesToRegister);
}
-TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoPrematureAllocation) {
- if (!SupportsJIT)
+TEST(RTDyldObjectLinkingLayerTest, TestAutoClaimResponsibilityForSymbols) {
+
+ OrcNativeTarget::initialize();
+
+ std::unique_ptr<TargetMachine> TM(
+ EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "",
+ SmallVector<std::string, 1>()));
+
+ if (!TM)
return;
- ExecutionSession ES;
+ // Our compiler is going to add a new symbol without telling ORC.
+ // This will test our ability to auto-claim responsibility later.
+ class FunkySimpleCompiler : public SimpleCompiler {
+ public:
+ FunkySimpleCompiler(TargetMachine &TM) : SimpleCompiler(TM) {}
- auto MM = std::make_shared<SectionMemoryManagerWrapper>();
+ CompileResult operator()(Module &M) {
+ Function *BarImpl =
+ Function::Create(TypeBuilder<void(), false>::get(M.getContext()),
+ GlobalValue::ExternalLinkage, "bar", &M);
+ BasicBlock *BarEntry =
+ BasicBlock::Create(M.getContext(), "entry", BarImpl);
+ IRBuilder<> B(BarEntry);
+ B.CreateRetVoid();
- RTDyldObjectLinkingLayer ObjLayer(ES, [&MM](VModuleKey K) {
- return RTDyldObjectLinkingLayer::Resources{
- MM, std::make_shared<NullResolver>()};
- });
- SimpleCompiler Compile(*TM);
+ return SimpleCompiler::operator()(M);
+ }
+ };
- // Create a pair of unrelated modules:
- //
- // Module 1:
- // int foo() { return 42; }
- // Module 2:
- // int bar() { return 7; }
- //
- // Both modules will share a memory manager. We want to verify that the
- // second object is not loaded before the first one is finalized. To do this
- // in a portable way, we abuse the
- // RuntimeDyld::MemoryManager::needsToReserveAllocationSpace hook, which is
- // called once per object before any sections are allocated.
-
- ModuleBuilder MB1(Context, "", "dummy");
+ // Create a module with two void() functions: foo and bar.
+ ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>());
+ ThreadSafeModule M;
{
- MB1.getModule()->setDataLayout(TM->createDataLayout());
- Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("foo");
- BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
- IRBuilder<> Builder(BarEntry);
- IntegerType *Int32Ty = IntegerType::get(Context, 32);
- Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
- Builder.CreateRet(FourtyTwo);
+ ModuleBuilder MB(*TSCtx.getContext(), TM->getTargetTriple().str(), "dummy");
+ MB.getModule()->setDataLayout(TM->createDataLayout());
+
+ Function *FooImpl = MB.createFunctionDecl<void()>("foo");
+ BasicBlock *FooEntry =
+ BasicBlock::Create(*TSCtx.getContext(), "entry", FooImpl);
+ IRBuilder<> B(FooEntry);
+ B.CreateRetVoid();
+
+ M = ThreadSafeModule(MB.takeModule(), std::move(TSCtx));
}
- auto Obj1 = Compile(*MB1.getModule());
-
- ModuleBuilder MB2(Context, "", "dummy");
- {
- MB2.getModule()->setDataLayout(TM->createDataLayout());
- Function *BarImpl = MB2.createFunctionDecl<int32_t(void)>("bar");
- BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
- IRBuilder<> Builder(BarEntry);
- IntegerType *Int32Ty = IntegerType::get(Context, 32);
- Value *Seven = ConstantInt::getSigned(Int32Ty, 7);
- Builder.CreateRet(Seven);
- }
- auto Obj2 = Compile(*MB2.getModule());
-
- auto K = ES.allocateVModule();
- cantFail(ObjLayer.addObject(K, std::move(Obj1)));
- cantFail(ObjLayer.addObject(ES.allocateVModule(), std::move(Obj2)));
- cantFail(ObjLayer.emitAndFinalize(K));
- cantFail(ObjLayer.removeObject(K));
-
- // Only one call to needsToReserveAllocationSpace should have been made.
- EXPECT_EQ(MM->NeedsToReserveAllocationSpaceCount, 1)
- << "More than one call to needsToReserveAllocationSpace "
- "(multiple unrelated objects loaded prior to finalization)";
-}
-
-TEST_F(RTDyldObjectLinkingLayerExecutionTest, TestNotifyLoadedSignature) {
+ // Create a simple stack and set the override flags option.
ExecutionSession ES;
+ auto &JD = ES.createJITDylib("main");
+ auto Foo = ES.intern("foo");
RTDyldObjectLinkingLayer ObjLayer(
- ES,
- [](VModuleKey) {
- return RTDyldObjectLinkingLayer::Resources{
- nullptr, std::make_shared<NullResolver>()};
- },
- [](VModuleKey, const object::ObjectFile &obj,
- const RuntimeDyld::LoadedObjectInfo &info) {});
+ ES, [](VModuleKey) { return llvm::make_unique<SectionMemoryManager>(); });
+ IRCompileLayer CompileLayer(ES, ObjLayer, FunkySimpleCompiler(*TM));
+
+ ObjLayer.setAutoClaimResponsibilityForObjectSymbols(true);
+
+ cantFail(CompileLayer.add(JD, ES.allocateVModule(), std::move(M)));
+ ES.lookup({&JD}, {Foo}, [](Expected<SymbolMap> R) { cantFail(std::move(R)); },
+ [](Error Err) { cantFail(std::move(Err)); },
+ NoDependenciesToRegister);
}
} // end anonymous namespace