blob: de99c022fb9dc66f5f277730b05edfac1b9d88fb [file] [log] [blame]
Lang Hames67de5d22017-02-20 05:45:14 +00001//===- RTDyldObjectLinkingLayerTest.cpp - RTDyld linking layer unit tests -===//
Lang Hames5f7fcef2015-10-29 03:53:42 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Lang Hames859d73c2016-01-09 19:50:40 +000010#include "OrcTestCommon.h"
Lang Hames5f7fcef2015-10-29 03:53:42 +000011#include "llvm/ExecutionEngine/ExecutionEngine.h"
12#include "llvm/ExecutionEngine/SectionMemoryManager.h"
13#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
14#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
Lang Hames2fe7acb2016-01-19 21:06:38 +000015#include "llvm/ExecutionEngine/Orc/NullResolver.h"
Lang Hames67de5d22017-02-20 05:45:14 +000016#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
Lang Hames5f7fcef2015-10-29 03:53:42 +000017#include "llvm/IR/Constants.h"
18#include "llvm/IR/LLVMContext.h"
19#include "gtest/gtest.h"
20
21using namespace llvm;
22using namespace llvm::orc;
23
24namespace {
25
Lang Hames67de5d22017-02-20 05:45:14 +000026class RTDyldObjectLinkingLayerExecutionTest : public testing::Test,
27 public OrcExecutionTest {
Mehdi Amini03b42e42016-04-14 21:59:01 +000028
Lang Hames859d73c2016-01-09 19:50:40 +000029};
30
NAKAMURA Takumi96e30312016-01-10 15:56:49 +000031class SectionMemoryManagerWrapper : public SectionMemoryManager {
32public:
33 int FinalizationCount = 0;
Lang Hames2fe7acb2016-01-19 21:06:38 +000034 int NeedsToReserveAllocationSpaceCount = 0;
35
36 bool needsToReserveAllocationSpace() override {
37 ++NeedsToReserveAllocationSpaceCount;
38 return SectionMemoryManager::needsToReserveAllocationSpace();
39 }
40
Eugene Zelenko6ac3f732016-01-26 18:48:36 +000041 bool finalizeMemory(std::string *ErrMsg = nullptr) override {
NAKAMURA Takumi96e30312016-01-10 15:56:49 +000042 ++FinalizationCount;
43 return SectionMemoryManager::finalizeMemory(ErrMsg);
44 }
45};
46
Lang Hames67de5d22017-02-20 05:45:14 +000047TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) {
Lang Hames5f7fcef2015-10-29 03:53:42 +000048 class SectionMemoryManagerWrapper : public SectionMemoryManager {
49 public:
50 SectionMemoryManagerWrapper(bool &DebugSeen) : DebugSeen(DebugSeen) {}
51 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
52 unsigned SectionID,
53 StringRef SectionName,
54 bool IsReadOnly) override {
55 if (SectionName == ".debug_str")
56 DebugSeen = true;
57 return SectionMemoryManager::allocateDataSection(Size, Alignment,
58 SectionID,
59 SectionName,
60 IsReadOnly);
61 }
62 private:
Lang Hamesd22bade2017-04-04 17:03:49 +000063 bool &DebugSeen;
Lang Hames5f7fcef2015-10-29 03:53:42 +000064 };
65
Lang Hames67de5d22017-02-20 05:45:14 +000066 RTDyldObjectLinkingLayer<> ObjLayer;
Lang Hames5f7fcef2015-10-29 03:53:42 +000067
Mehdi Amini03b42e42016-04-14 21:59:01 +000068 LLVMContext Context;
69 auto M = llvm::make_unique<Module>("", Context);
Lang Hames5f7fcef2015-10-29 03:53:42 +000070 M->setTargetTriple("x86_64-unknown-linux-gnu");
Mehdi Amini03b42e42016-04-14 21:59:01 +000071 Type *Int32Ty = IntegerType::get(Context, 32);
Lang Hames5f7fcef2015-10-29 03:53:42 +000072 GlobalVariable *GV =
73 new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage,
74 ConstantInt::get(Int32Ty, 42), "foo");
75
76 GV->setSection(".debug_str");
77
Lang Hamesd22bade2017-04-04 17:03:49 +000078
79 // Initialize the native target in case this is the first unit test
80 // to try to build a TM.
81 OrcNativeTarget::initialize();
Lang Hames5f7fcef2015-10-29 03:53:42 +000082 std::unique_ptr<TargetMachine> TM(
83 EngineBuilder().selectTarget(Triple(M->getTargetTriple()), "", "",
84 SmallVector<std::string, 1>()));
85 if (!TM)
86 return;
87
88 auto OwningObj = SimpleCompiler(*TM)(*M);
89 std::vector<object::ObjectFile*> Objs;
90 Objs.push_back(OwningObj.getBinary());
91
92 bool DebugSectionSeen = false;
93 SectionMemoryManagerWrapper SMMW(DebugSectionSeen);
94 auto Resolver =
95 createLambdaResolver(
96 [](const std::string &Name) {
Lang Hamesad4a9112016-08-01 20:49:11 +000097 return JITSymbol(nullptr);
Lang Hames5f7fcef2015-10-29 03:53:42 +000098 },
99 [](const std::string &Name) {
Lang Hamesad4a9112016-08-01 20:49:11 +0000100 return JITSymbol(nullptr);
Lang Hames5f7fcef2015-10-29 03:53:42 +0000101 });
102
103 {
104 // Test with ProcessAllSections = false (the default).
105 auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver);
Lang Hamesd22bade2017-04-04 17:03:49 +0000106 ObjLayer.emitAndFinalize(H);
Lang Hames5f7fcef2015-10-29 03:53:42 +0000107 EXPECT_EQ(DebugSectionSeen, false)
108 << "Unexpected debug info section";
109 ObjLayer.removeObjectSet(H);
110 }
111
112 {
113 // Test with ProcessAllSections = true.
114 ObjLayer.setProcessAllSections(true);
115 auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver);
Lang Hamesd22bade2017-04-04 17:03:49 +0000116 ObjLayer.emitAndFinalize(H);
Lang Hames5f7fcef2015-10-29 03:53:42 +0000117 EXPECT_EQ(DebugSectionSeen, true)
118 << "Expected debug info section not seen";
119 ObjLayer.removeObjectSet(H);
120 }
121}
122
Lang Hames67de5d22017-02-20 05:45:14 +0000123TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoDuplicateFinalization) {
Lang Hames859d73c2016-01-09 19:50:40 +0000124 if (!TM)
125 return;
126
Lang Hames67de5d22017-02-20 05:45:14 +0000127 RTDyldObjectLinkingLayer<> ObjLayer;
Lang Hames859d73c2016-01-09 19:50:40 +0000128 SimpleCompiler Compile(*TM);
129
130 // Create a pair of modules that will trigger recursive finalization:
131 // Module 1:
132 // int bar() { return 42; }
133 // Module 2:
134 // int bar();
135 // int foo() { return bar(); }
Lang Hames133f1532016-01-18 01:00:19 +0000136 //
137 // Verify that the memory manager is only finalized once (for Module 2).
138 // Failure suggests that finalize is being called on the inner RTDyld
139 // instance (for Module 1) which is unsafe, as it will prevent relocation of
140 // Module 2.
Lang Hames859d73c2016-01-09 19:50:40 +0000141
Mehdi Amini03b42e42016-04-14 21:59:01 +0000142 ModuleBuilder MB1(Context, "", "dummy");
Lang Hames859d73c2016-01-09 19:50:40 +0000143 {
144 MB1.getModule()->setDataLayout(TM->createDataLayout());
145 Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("bar");
Mehdi Amini03b42e42016-04-14 21:59:01 +0000146 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
Lang Hames859d73c2016-01-09 19:50:40 +0000147 IRBuilder<> Builder(BarEntry);
Mehdi Amini03b42e42016-04-14 21:59:01 +0000148 IntegerType *Int32Ty = IntegerType::get(Context, 32);
Lang Hames859d73c2016-01-09 19:50:40 +0000149 Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
150 Builder.CreateRet(FourtyTwo);
151 }
152
153 auto Obj1 = Compile(*MB1.getModule());
154 std::vector<object::ObjectFile*> Obj1Set;
155 Obj1Set.push_back(Obj1.getBinary());
156
Mehdi Amini03b42e42016-04-14 21:59:01 +0000157 ModuleBuilder MB2(Context, "", "dummy");
Lang Hames859d73c2016-01-09 19:50:40 +0000158 {
159 MB2.getModule()->setDataLayout(TM->createDataLayout());
160 Function *BarDecl = MB2.createFunctionDecl<int32_t(void)>("bar");
161 Function *FooImpl = MB2.createFunctionDecl<int32_t(void)>("foo");
Mehdi Amini03b42e42016-04-14 21:59:01 +0000162 BasicBlock *FooEntry = BasicBlock::Create(Context, "entry", FooImpl);
Lang Hames859d73c2016-01-09 19:50:40 +0000163 IRBuilder<> Builder(FooEntry);
164 Builder.CreateRet(Builder.CreateCall(BarDecl));
165 }
166 auto Obj2 = Compile(*MB2.getModule());
167 std::vector<object::ObjectFile*> Obj2Set;
168 Obj2Set.push_back(Obj2.getBinary());
169
170 auto Resolver =
171 createLambdaResolver(
172 [&](const std::string &Name) {
173 if (auto Sym = ObjLayer.findSymbol(Name, true))
Lang Hamesad4a9112016-08-01 20:49:11 +0000174 return Sym;
175 return JITSymbol(nullptr);
Lang Hames859d73c2016-01-09 19:50:40 +0000176 },
177 [](const std::string &Name) {
Lang Hamesad4a9112016-08-01 20:49:11 +0000178 return JITSymbol(nullptr);
Lang Hames859d73c2016-01-09 19:50:40 +0000179 });
180
181 SectionMemoryManagerWrapper SMMW;
182 ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &*Resolver);
183 auto H = ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &*Resolver);
184 ObjLayer.emitAndFinalize(H);
185
186 // Finalization of module 2 should trigger finalization of module 1.
187 // Verify that finalize on SMMW is only called once.
188 EXPECT_EQ(SMMW.FinalizationCount, 1)
189 << "Extra call to finalize";
190}
191
Lang Hames67de5d22017-02-20 05:45:14 +0000192TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoPrematureAllocation) {
Lang Hames2fe7acb2016-01-19 21:06:38 +0000193 if (!TM)
194 return;
195
Lang Hames67de5d22017-02-20 05:45:14 +0000196 RTDyldObjectLinkingLayer<> ObjLayer;
Lang Hames2fe7acb2016-01-19 21:06:38 +0000197 SimpleCompiler Compile(*TM);
198
199 // Create a pair of unrelated modules:
200 //
201 // Module 1:
202 // int foo() { return 42; }
203 // Module 2:
204 // int bar() { return 7; }
205 //
206 // Both modules will share a memory manager. We want to verify that the
207 // second object is not loaded before the first one is finalized. To do this
208 // in a portable way, we abuse the
209 // RuntimeDyld::MemoryManager::needsToReserveAllocationSpace hook, which is
210 // called once per object before any sections are allocated.
211
Mehdi Amini03b42e42016-04-14 21:59:01 +0000212 ModuleBuilder MB1(Context, "", "dummy");
Lang Hames2fe7acb2016-01-19 21:06:38 +0000213 {
214 MB1.getModule()->setDataLayout(TM->createDataLayout());
215 Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("foo");
Mehdi Amini03b42e42016-04-14 21:59:01 +0000216 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
Lang Hames2fe7acb2016-01-19 21:06:38 +0000217 IRBuilder<> Builder(BarEntry);
Mehdi Amini03b42e42016-04-14 21:59:01 +0000218 IntegerType *Int32Ty = IntegerType::get(Context, 32);
Lang Hames2fe7acb2016-01-19 21:06:38 +0000219 Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
220 Builder.CreateRet(FourtyTwo);
221 }
222
223 auto Obj1 = Compile(*MB1.getModule());
224 std::vector<object::ObjectFile*> Obj1Set;
225 Obj1Set.push_back(Obj1.getBinary());
226
Mehdi Amini03b42e42016-04-14 21:59:01 +0000227 ModuleBuilder MB2(Context, "", "dummy");
Lang Hames2fe7acb2016-01-19 21:06:38 +0000228 {
229 MB2.getModule()->setDataLayout(TM->createDataLayout());
230 Function *BarImpl = MB2.createFunctionDecl<int32_t(void)>("bar");
Mehdi Amini03b42e42016-04-14 21:59:01 +0000231 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
Lang Hames2fe7acb2016-01-19 21:06:38 +0000232 IRBuilder<> Builder(BarEntry);
Mehdi Amini03b42e42016-04-14 21:59:01 +0000233 IntegerType *Int32Ty = IntegerType::get(Context, 32);
Lang Hames2fe7acb2016-01-19 21:06:38 +0000234 Value *Seven = ConstantInt::getSigned(Int32Ty, 7);
235 Builder.CreateRet(Seven);
236 }
237 auto Obj2 = Compile(*MB2.getModule());
238 std::vector<object::ObjectFile*> Obj2Set;
239 Obj2Set.push_back(Obj2.getBinary());
240
241 SectionMemoryManagerWrapper SMMW;
242 NullResolver NR;
243 auto H = ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &NR);
244 ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &NR);
245 ObjLayer.emitAndFinalize(H);
246
247 // Only one call to needsToReserveAllocationSpace should have been made.
248 EXPECT_EQ(SMMW.NeedsToReserveAllocationSpaceCount, 1)
249 << "More than one call to needsToReserveAllocationSpace "
250 "(multiple unrelated objects loaded prior to finalization)";
251}
252
Eugene Zelenko6ac3f732016-01-26 18:48:36 +0000253} // end anonymous namespace