blob: f4cec0cc9309e502e24afe475a625f65fcbcedf0 [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:
63 bool DebugSeen;
64 };
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
78 std::unique_ptr<TargetMachine> TM(
79 EngineBuilder().selectTarget(Triple(M->getTargetTriple()), "", "",
80 SmallVector<std::string, 1>()));
81 if (!TM)
82 return;
83
84 auto OwningObj = SimpleCompiler(*TM)(*M);
85 std::vector<object::ObjectFile*> Objs;
86 Objs.push_back(OwningObj.getBinary());
87
88 bool DebugSectionSeen = false;
89 SectionMemoryManagerWrapper SMMW(DebugSectionSeen);
90 auto Resolver =
91 createLambdaResolver(
92 [](const std::string &Name) {
Lang Hamesad4a9112016-08-01 20:49:11 +000093 return JITSymbol(nullptr);
Lang Hames5f7fcef2015-10-29 03:53:42 +000094 },
95 [](const std::string &Name) {
Lang Hamesad4a9112016-08-01 20:49:11 +000096 return JITSymbol(nullptr);
Lang Hames5f7fcef2015-10-29 03:53:42 +000097 });
98
99 {
100 // Test with ProcessAllSections = false (the default).
101 auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver);
102 EXPECT_EQ(DebugSectionSeen, false)
103 << "Unexpected debug info section";
104 ObjLayer.removeObjectSet(H);
105 }
106
107 {
108 // Test with ProcessAllSections = true.
109 ObjLayer.setProcessAllSections(true);
110 auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver);
111 EXPECT_EQ(DebugSectionSeen, true)
112 << "Expected debug info section not seen";
113 ObjLayer.removeObjectSet(H);
114 }
115}
116
Lang Hames67de5d22017-02-20 05:45:14 +0000117TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoDuplicateFinalization) {
Lang Hames859d73c2016-01-09 19:50:40 +0000118 if (!TM)
119 return;
120
Lang Hames67de5d22017-02-20 05:45:14 +0000121 RTDyldObjectLinkingLayer<> ObjLayer;
Lang Hames859d73c2016-01-09 19:50:40 +0000122 SimpleCompiler Compile(*TM);
123
124 // Create a pair of modules that will trigger recursive finalization:
125 // Module 1:
126 // int bar() { return 42; }
127 // Module 2:
128 // int bar();
129 // int foo() { return bar(); }
Lang Hames133f1532016-01-18 01:00:19 +0000130 //
131 // Verify that the memory manager is only finalized once (for Module 2).
132 // Failure suggests that finalize is being called on the inner RTDyld
133 // instance (for Module 1) which is unsafe, as it will prevent relocation of
134 // Module 2.
Lang Hames859d73c2016-01-09 19:50:40 +0000135
Mehdi Amini03b42e42016-04-14 21:59:01 +0000136 ModuleBuilder MB1(Context, "", "dummy");
Lang Hames859d73c2016-01-09 19:50:40 +0000137 {
138 MB1.getModule()->setDataLayout(TM->createDataLayout());
139 Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("bar");
Mehdi Amini03b42e42016-04-14 21:59:01 +0000140 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
Lang Hames859d73c2016-01-09 19:50:40 +0000141 IRBuilder<> Builder(BarEntry);
Mehdi Amini03b42e42016-04-14 21:59:01 +0000142 IntegerType *Int32Ty = IntegerType::get(Context, 32);
Lang Hames859d73c2016-01-09 19:50:40 +0000143 Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
144 Builder.CreateRet(FourtyTwo);
145 }
146
147 auto Obj1 = Compile(*MB1.getModule());
148 std::vector<object::ObjectFile*> Obj1Set;
149 Obj1Set.push_back(Obj1.getBinary());
150
Mehdi Amini03b42e42016-04-14 21:59:01 +0000151 ModuleBuilder MB2(Context, "", "dummy");
Lang Hames859d73c2016-01-09 19:50:40 +0000152 {
153 MB2.getModule()->setDataLayout(TM->createDataLayout());
154 Function *BarDecl = MB2.createFunctionDecl<int32_t(void)>("bar");
155 Function *FooImpl = MB2.createFunctionDecl<int32_t(void)>("foo");
Mehdi Amini03b42e42016-04-14 21:59:01 +0000156 BasicBlock *FooEntry = BasicBlock::Create(Context, "entry", FooImpl);
Lang Hames859d73c2016-01-09 19:50:40 +0000157 IRBuilder<> Builder(FooEntry);
158 Builder.CreateRet(Builder.CreateCall(BarDecl));
159 }
160 auto Obj2 = Compile(*MB2.getModule());
161 std::vector<object::ObjectFile*> Obj2Set;
162 Obj2Set.push_back(Obj2.getBinary());
163
164 auto Resolver =
165 createLambdaResolver(
166 [&](const std::string &Name) {
167 if (auto Sym = ObjLayer.findSymbol(Name, true))
Lang Hamesad4a9112016-08-01 20:49:11 +0000168 return Sym;
169 return JITSymbol(nullptr);
Lang Hames859d73c2016-01-09 19:50:40 +0000170 },
171 [](const std::string &Name) {
Lang Hamesad4a9112016-08-01 20:49:11 +0000172 return JITSymbol(nullptr);
Lang Hames859d73c2016-01-09 19:50:40 +0000173 });
174
175 SectionMemoryManagerWrapper SMMW;
176 ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &*Resolver);
177 auto H = ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &*Resolver);
178 ObjLayer.emitAndFinalize(H);
179
180 // Finalization of module 2 should trigger finalization of module 1.
181 // Verify that finalize on SMMW is only called once.
182 EXPECT_EQ(SMMW.FinalizationCount, 1)
183 << "Extra call to finalize";
184}
185
Lang Hames67de5d22017-02-20 05:45:14 +0000186TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoPrematureAllocation) {
Lang Hames2fe7acb2016-01-19 21:06:38 +0000187 if (!TM)
188 return;
189
Lang Hames67de5d22017-02-20 05:45:14 +0000190 RTDyldObjectLinkingLayer<> ObjLayer;
Lang Hames2fe7acb2016-01-19 21:06:38 +0000191 SimpleCompiler Compile(*TM);
192
193 // Create a pair of unrelated modules:
194 //
195 // Module 1:
196 // int foo() { return 42; }
197 // Module 2:
198 // int bar() { return 7; }
199 //
200 // Both modules will share a memory manager. We want to verify that the
201 // second object is not loaded before the first one is finalized. To do this
202 // in a portable way, we abuse the
203 // RuntimeDyld::MemoryManager::needsToReserveAllocationSpace hook, which is
204 // called once per object before any sections are allocated.
205
Mehdi Amini03b42e42016-04-14 21:59:01 +0000206 ModuleBuilder MB1(Context, "", "dummy");
Lang Hames2fe7acb2016-01-19 21:06:38 +0000207 {
208 MB1.getModule()->setDataLayout(TM->createDataLayout());
209 Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("foo");
Mehdi Amini03b42e42016-04-14 21:59:01 +0000210 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
Lang Hames2fe7acb2016-01-19 21:06:38 +0000211 IRBuilder<> Builder(BarEntry);
Mehdi Amini03b42e42016-04-14 21:59:01 +0000212 IntegerType *Int32Ty = IntegerType::get(Context, 32);
Lang Hames2fe7acb2016-01-19 21:06:38 +0000213 Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
214 Builder.CreateRet(FourtyTwo);
215 }
216
217 auto Obj1 = Compile(*MB1.getModule());
218 std::vector<object::ObjectFile*> Obj1Set;
219 Obj1Set.push_back(Obj1.getBinary());
220
Mehdi Amini03b42e42016-04-14 21:59:01 +0000221 ModuleBuilder MB2(Context, "", "dummy");
Lang Hames2fe7acb2016-01-19 21:06:38 +0000222 {
223 MB2.getModule()->setDataLayout(TM->createDataLayout());
224 Function *BarImpl = MB2.createFunctionDecl<int32_t(void)>("bar");
Mehdi Amini03b42e42016-04-14 21:59:01 +0000225 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
Lang Hames2fe7acb2016-01-19 21:06:38 +0000226 IRBuilder<> Builder(BarEntry);
Mehdi Amini03b42e42016-04-14 21:59:01 +0000227 IntegerType *Int32Ty = IntegerType::get(Context, 32);
Lang Hames2fe7acb2016-01-19 21:06:38 +0000228 Value *Seven = ConstantInt::getSigned(Int32Ty, 7);
229 Builder.CreateRet(Seven);
230 }
231 auto Obj2 = Compile(*MB2.getModule());
232 std::vector<object::ObjectFile*> Obj2Set;
233 Obj2Set.push_back(Obj2.getBinary());
234
235 SectionMemoryManagerWrapper SMMW;
236 NullResolver NR;
237 auto H = ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &NR);
238 ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &NR);
239 ObjLayer.emitAndFinalize(H);
240
241 // Only one call to needsToReserveAllocationSpace should have been made.
242 EXPECT_EQ(SMMW.NeedsToReserveAllocationSpaceCount, 1)
243 << "More than one call to needsToReserveAllocationSpace "
244 "(multiple unrelated objects loaded prior to finalization)";
245}
246
Eugene Zelenko6ac3f732016-01-26 18:48:36 +0000247} // end anonymous namespace