1 //===- RTDyldObjectLinkingLayerTest.cpp - RTDyld linking layer unit tests -===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
11 #include "OrcTestCommon.h"
12 #include "llvm/ExecutionEngine/ExecutionEngine.h"
13 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
14 #include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
15 #include "llvm/ExecutionEngine/Orc/Legacy.h"
16 #include "llvm/ExecutionEngine/Orc/NullResolver.h"
17 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
18 #include "llvm/IR/Constants.h"
19 #include "llvm/IR/LLVMContext.h"
20 #include "gtest/gtest.h"
23 using namespace llvm::orc
;
27 class RTDyldObjectLinkingLayerExecutionTest
: public testing::Test
,
28 public OrcExecutionTest
{
32 class SectionMemoryManagerWrapper
: public SectionMemoryManager
{
34 int FinalizationCount
= 0;
35 int NeedsToReserveAllocationSpaceCount
= 0;
37 bool needsToReserveAllocationSpace() override
{
38 ++NeedsToReserveAllocationSpaceCount
;
39 return SectionMemoryManager::needsToReserveAllocationSpace();
42 bool finalizeMemory(std::string
*ErrMsg
= nullptr) override
{
44 return SectionMemoryManager::finalizeMemory(ErrMsg
);
48 TEST(RTDyldObjectLinkingLayerTest
, TestSetProcessAllSections
) {
49 class MemoryManagerWrapper
: public SectionMemoryManager
{
51 MemoryManagerWrapper(bool &DebugSeen
) : DebugSeen(DebugSeen
) {}
52 uint8_t *allocateDataSection(uintptr_t Size
, unsigned Alignment
,
54 StringRef SectionName
,
55 bool IsReadOnly
) override
{
56 if (SectionName
== ".debug_str")
58 return SectionMemoryManager::allocateDataSection(Size
, Alignment
,
67 bool DebugSectionSeen
= false;
68 auto MM
= std::make_shared
<MemoryManagerWrapper
>(DebugSectionSeen
);
72 RTDyldObjectLinkingLayer
ObjLayer(ES
, [&MM
](VModuleKey
) {
73 return RTDyldObjectLinkingLayer::Resources
{
74 MM
, std::make_shared
<NullResolver
>()};
78 auto M
= llvm::make_unique
<Module
>("", Context
);
79 M
->setTargetTriple("x86_64-unknown-linux-gnu");
80 Type
*Int32Ty
= IntegerType::get(Context
, 32);
82 new GlobalVariable(*M
, Int32Ty
, false, GlobalValue::ExternalLinkage
,
83 ConstantInt::get(Int32Ty
, 42), "foo");
85 GV
->setSection(".debug_str");
88 // Initialize the native target in case this is the first unit test
89 // to try to build a TM.
90 OrcNativeTarget::initialize();
91 std::unique_ptr
<TargetMachine
> TM(
92 EngineBuilder().selectTarget(Triple(M
->getTargetTriple()), "", "",
93 SmallVector
<std::string
, 1>()));
97 auto Obj
= SimpleCompiler(*TM
)(*M
);
100 // Test with ProcessAllSections = false (the default).
101 auto K
= ES
.allocateVModule();
102 cantFail(ObjLayer
.addObject(
103 K
, MemoryBuffer::getMemBufferCopy(Obj
->getBuffer())));
104 cantFail(ObjLayer
.emitAndFinalize(K
));
105 EXPECT_EQ(DebugSectionSeen
, false)
106 << "Unexpected debug info section";
107 cantFail(ObjLayer
.removeObject(K
));
111 // Test with ProcessAllSections = true.
112 ObjLayer
.setProcessAllSections(true);
113 auto K
= ES
.allocateVModule();
114 cantFail(ObjLayer
.addObject(K
, std::move(Obj
)));
115 cantFail(ObjLayer
.emitAndFinalize(K
));
116 EXPECT_EQ(DebugSectionSeen
, true)
117 << "Expected debug info section not seen";
118 cantFail(ObjLayer
.removeObject(K
));
122 TEST_F(RTDyldObjectLinkingLayerExecutionTest
, NoDuplicateFinalization
) {
128 auto MM
= std::make_shared
<SectionMemoryManagerWrapper
>();
130 std::map
<orc::VModuleKey
, std::shared_ptr
<orc::SymbolResolver
>> Resolvers
;
132 RTDyldObjectLinkingLayer
ObjLayer(ES
, [&](VModuleKey K
) {
133 auto I
= Resolvers
.find(K
);
134 assert(I
!= Resolvers
.end() && "Missing resolver");
135 auto R
= std::move(I
->second
);
137 return RTDyldObjectLinkingLayer::Resources
{MM
, std::move(R
)};
139 SimpleCompiler
Compile(*TM
);
141 // Create a pair of modules that will trigger recursive finalization:
143 // int bar() { return 42; }
146 // int foo() { return bar(); }
148 // Verify that the memory manager is only finalized once (for Module 2).
149 // Failure suggests that finalize is being called on the inner RTDyld
150 // instance (for Module 1) which is unsafe, as it will prevent relocation of
153 ModuleBuilder
MB1(Context
, "", "dummy");
155 MB1
.getModule()->setDataLayout(TM
->createDataLayout());
156 Function
*BarImpl
= MB1
.createFunctionDecl
<int32_t(void)>("bar");
157 BasicBlock
*BarEntry
= BasicBlock::Create(Context
, "entry", BarImpl
);
158 IRBuilder
<> Builder(BarEntry
);
159 IntegerType
*Int32Ty
= IntegerType::get(Context
, 32);
160 Value
*FourtyTwo
= ConstantInt::getSigned(Int32Ty
, 42);
161 Builder
.CreateRet(FourtyTwo
);
164 auto Obj1
= Compile(*MB1
.getModule());
166 ModuleBuilder
MB2(Context
, "", "dummy");
168 MB2
.getModule()->setDataLayout(TM
->createDataLayout());
169 Function
*BarDecl
= MB2
.createFunctionDecl
<int32_t(void)>("bar");
170 Function
*FooImpl
= MB2
.createFunctionDecl
<int32_t(void)>("foo");
171 BasicBlock
*FooEntry
= BasicBlock::Create(Context
, "entry", FooImpl
);
172 IRBuilder
<> Builder(FooEntry
);
173 Builder
.CreateRet(Builder
.CreateCall(BarDecl
));
175 auto Obj2
= Compile(*MB2
.getModule());
177 auto K1
= ES
.allocateVModule();
178 Resolvers
[K1
] = std::make_shared
<NullResolver
>();
179 cantFail(ObjLayer
.addObject(K1
, std::move(Obj1
)));
181 auto K2
= ES
.allocateVModule();
182 auto LegacyLookup
= [&](const std::string
&Name
) {
183 return ObjLayer
.findSymbol(Name
, true);
186 Resolvers
[K2
] = createSymbolResolver(
187 [&](const SymbolNameSet
&Symbols
) {
189 getResponsibilitySetWithLegacyFn(Symbols
, LegacyLookup
));
191 [&](std::shared_ptr
<AsynchronousSymbolQuery
> Query
,
192 const SymbolNameSet
&Symbols
) {
193 return lookupWithLegacyFn(ES
, *Query
, Symbols
, LegacyLookup
);
196 cantFail(ObjLayer
.addObject(K2
, std::move(Obj2
)));
197 cantFail(ObjLayer
.emitAndFinalize(K2
));
198 cantFail(ObjLayer
.removeObject(K2
));
200 // Finalization of module 2 should trigger finalization of module 1.
201 // Verify that finalize on SMMW is only called once.
202 EXPECT_EQ(MM
->FinalizationCount
, 1)
203 << "Extra call to finalize";
206 TEST_F(RTDyldObjectLinkingLayerExecutionTest
, NoPrematureAllocation
) {
212 auto MM
= std::make_shared
<SectionMemoryManagerWrapper
>();
214 RTDyldObjectLinkingLayer
ObjLayer(ES
, [&MM
](VModuleKey K
) {
215 return RTDyldObjectLinkingLayer::Resources
{
216 MM
, std::make_shared
<NullResolver
>()};
218 SimpleCompiler
Compile(*TM
);
220 // Create a pair of unrelated modules:
223 // int foo() { return 42; }
225 // int bar() { return 7; }
227 // Both modules will share a memory manager. We want to verify that the
228 // second object is not loaded before the first one is finalized. To do this
229 // in a portable way, we abuse the
230 // RuntimeDyld::MemoryManager::needsToReserveAllocationSpace hook, which is
231 // called once per object before any sections are allocated.
233 ModuleBuilder
MB1(Context
, "", "dummy");
235 MB1
.getModule()->setDataLayout(TM
->createDataLayout());
236 Function
*BarImpl
= MB1
.createFunctionDecl
<int32_t(void)>("foo");
237 BasicBlock
*BarEntry
= BasicBlock::Create(Context
, "entry", BarImpl
);
238 IRBuilder
<> Builder(BarEntry
);
239 IntegerType
*Int32Ty
= IntegerType::get(Context
, 32);
240 Value
*FourtyTwo
= ConstantInt::getSigned(Int32Ty
, 42);
241 Builder
.CreateRet(FourtyTwo
);
244 auto Obj1
= Compile(*MB1
.getModule());
246 ModuleBuilder
MB2(Context
, "", "dummy");
248 MB2
.getModule()->setDataLayout(TM
->createDataLayout());
249 Function
*BarImpl
= MB2
.createFunctionDecl
<int32_t(void)>("bar");
250 BasicBlock
*BarEntry
= BasicBlock::Create(Context
, "entry", BarImpl
);
251 IRBuilder
<> Builder(BarEntry
);
252 IntegerType
*Int32Ty
= IntegerType::get(Context
, 32);
253 Value
*Seven
= ConstantInt::getSigned(Int32Ty
, 7);
254 Builder
.CreateRet(Seven
);
256 auto Obj2
= Compile(*MB2
.getModule());
258 auto K
= ES
.allocateVModule();
259 cantFail(ObjLayer
.addObject(K
, std::move(Obj1
)));
260 cantFail(ObjLayer
.addObject(ES
.allocateVModule(), std::move(Obj2
)));
261 cantFail(ObjLayer
.emitAndFinalize(K
));
262 cantFail(ObjLayer
.removeObject(K
));
264 // Only one call to needsToReserveAllocationSpace should have been made.
265 EXPECT_EQ(MM
->NeedsToReserveAllocationSpaceCount
, 1)
266 << "More than one call to needsToReserveAllocationSpace "
267 "(multiple unrelated objects loaded prior to finalization)";
270 TEST_F(RTDyldObjectLinkingLayerExecutionTest
, TestNotifyLoadedSignature
) {
272 RTDyldObjectLinkingLayer
ObjLayer(
275 return RTDyldObjectLinkingLayer::Resources
{
276 nullptr, std::make_shared
<NullResolver
>()};
278 [](VModuleKey
, const object::ObjectFile
&obj
,
279 const RuntimeDyld::LoadedObjectInfo
&info
) {});
282 } // end anonymous namespace