xref: /aosp_15_r20/external/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- ObjectLinkingLayerTest.cpp - Unit tests for object linking layer --===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker 
10*9880d681SAndroid Build Coastguard Worker #include "OrcTestCommon.h"
11*9880d681SAndroid Build Coastguard Worker #include "llvm/ExecutionEngine/ExecutionEngine.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/ExecutionEngine/SectionMemoryManager.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/ExecutionEngine/Orc/NullResolver.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Constants.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/LLVMContext.h"
19*9880d681SAndroid Build Coastguard Worker #include "gtest/gtest.h"
20*9880d681SAndroid Build Coastguard Worker 
21*9880d681SAndroid Build Coastguard Worker using namespace llvm;
22*9880d681SAndroid Build Coastguard Worker using namespace llvm::orc;
23*9880d681SAndroid Build Coastguard Worker 
24*9880d681SAndroid Build Coastguard Worker namespace {
25*9880d681SAndroid Build Coastguard Worker 
26*9880d681SAndroid Build Coastguard Worker class ObjectLinkingLayerExecutionTest : public testing::Test,
27*9880d681SAndroid Build Coastguard Worker                                         public OrcExecutionTest {
28*9880d681SAndroid Build Coastguard Worker 
29*9880d681SAndroid Build Coastguard Worker };
30*9880d681SAndroid Build Coastguard Worker 
31*9880d681SAndroid Build Coastguard Worker class SectionMemoryManagerWrapper : public SectionMemoryManager {
32*9880d681SAndroid Build Coastguard Worker public:
33*9880d681SAndroid Build Coastguard Worker   int FinalizationCount = 0;
34*9880d681SAndroid Build Coastguard Worker   int NeedsToReserveAllocationSpaceCount = 0;
35*9880d681SAndroid Build Coastguard Worker 
needsToReserveAllocationSpace()36*9880d681SAndroid Build Coastguard Worker   bool needsToReserveAllocationSpace() override {
37*9880d681SAndroid Build Coastguard Worker     ++NeedsToReserveAllocationSpaceCount;
38*9880d681SAndroid Build Coastguard Worker     return SectionMemoryManager::needsToReserveAllocationSpace();
39*9880d681SAndroid Build Coastguard Worker   }
40*9880d681SAndroid Build Coastguard Worker 
finalizeMemory(std::string * ErrMsg=nullptr)41*9880d681SAndroid Build Coastguard Worker   bool finalizeMemory(std::string *ErrMsg = nullptr) override {
42*9880d681SAndroid Build Coastguard Worker     ++FinalizationCount;
43*9880d681SAndroid Build Coastguard Worker     return SectionMemoryManager::finalizeMemory(ErrMsg);
44*9880d681SAndroid Build Coastguard Worker   }
45*9880d681SAndroid Build Coastguard Worker };
46*9880d681SAndroid Build Coastguard Worker 
TEST(ObjectLinkingLayerTest,TestSetProcessAllSections)47*9880d681SAndroid Build Coastguard Worker TEST(ObjectLinkingLayerTest, TestSetProcessAllSections) {
48*9880d681SAndroid Build Coastguard Worker   class SectionMemoryManagerWrapper : public SectionMemoryManager {
49*9880d681SAndroid Build Coastguard Worker   public:
50*9880d681SAndroid Build Coastguard Worker     SectionMemoryManagerWrapper(bool &DebugSeen) : DebugSeen(DebugSeen) {}
51*9880d681SAndroid Build Coastguard Worker     uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
52*9880d681SAndroid Build Coastguard Worker                                  unsigned SectionID,
53*9880d681SAndroid Build Coastguard Worker                                  StringRef SectionName,
54*9880d681SAndroid Build Coastguard Worker                                  bool IsReadOnly) override {
55*9880d681SAndroid Build Coastguard Worker       if (SectionName == ".debug_str")
56*9880d681SAndroid Build Coastguard Worker         DebugSeen = true;
57*9880d681SAndroid Build Coastguard Worker       return SectionMemoryManager::allocateDataSection(Size, Alignment,
58*9880d681SAndroid Build Coastguard Worker                                                          SectionID,
59*9880d681SAndroid Build Coastguard Worker                                                          SectionName,
60*9880d681SAndroid Build Coastguard Worker                                                          IsReadOnly);
61*9880d681SAndroid Build Coastguard Worker     }
62*9880d681SAndroid Build Coastguard Worker   private:
63*9880d681SAndroid Build Coastguard Worker     bool DebugSeen;
64*9880d681SAndroid Build Coastguard Worker   };
65*9880d681SAndroid Build Coastguard Worker 
66*9880d681SAndroid Build Coastguard Worker   ObjectLinkingLayer<> ObjLayer;
67*9880d681SAndroid Build Coastguard Worker 
68*9880d681SAndroid Build Coastguard Worker   LLVMContext Context;
69*9880d681SAndroid Build Coastguard Worker   auto M = llvm::make_unique<Module>("", Context);
70*9880d681SAndroid Build Coastguard Worker   M->setTargetTriple("x86_64-unknown-linux-gnu");
71*9880d681SAndroid Build Coastguard Worker   Type *Int32Ty = IntegerType::get(Context, 32);
72*9880d681SAndroid Build Coastguard Worker   GlobalVariable *GV =
73*9880d681SAndroid Build Coastguard Worker     new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage,
74*9880d681SAndroid Build Coastguard Worker                          ConstantInt::get(Int32Ty, 42), "foo");
75*9880d681SAndroid Build Coastguard Worker 
76*9880d681SAndroid Build Coastguard Worker   GV->setSection(".debug_str");
77*9880d681SAndroid Build Coastguard Worker 
78*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<TargetMachine> TM(
79*9880d681SAndroid Build Coastguard Worker     EngineBuilder().selectTarget(Triple(M->getTargetTriple()), "", "",
80*9880d681SAndroid Build Coastguard Worker                                  SmallVector<std::string, 1>()));
81*9880d681SAndroid Build Coastguard Worker   if (!TM)
82*9880d681SAndroid Build Coastguard Worker     return;
83*9880d681SAndroid Build Coastguard Worker 
84*9880d681SAndroid Build Coastguard Worker   auto OwningObj = SimpleCompiler(*TM)(*M);
85*9880d681SAndroid Build Coastguard Worker   std::vector<object::ObjectFile*> Objs;
86*9880d681SAndroid Build Coastguard Worker   Objs.push_back(OwningObj.getBinary());
87*9880d681SAndroid Build Coastguard Worker 
88*9880d681SAndroid Build Coastguard Worker   bool DebugSectionSeen = false;
89*9880d681SAndroid Build Coastguard Worker   SectionMemoryManagerWrapper SMMW(DebugSectionSeen);
90*9880d681SAndroid Build Coastguard Worker   auto Resolver =
91*9880d681SAndroid Build Coastguard Worker     createLambdaResolver(
92*9880d681SAndroid Build Coastguard Worker       [](const std::string &Name) {
93*9880d681SAndroid Build Coastguard Worker         return RuntimeDyld::SymbolInfo(nullptr);
94*9880d681SAndroid Build Coastguard Worker       },
95*9880d681SAndroid Build Coastguard Worker       [](const std::string &Name) {
96*9880d681SAndroid Build Coastguard Worker         return RuntimeDyld::SymbolInfo(nullptr);
97*9880d681SAndroid Build Coastguard Worker       });
98*9880d681SAndroid Build Coastguard Worker 
99*9880d681SAndroid Build Coastguard Worker   {
100*9880d681SAndroid Build Coastguard Worker     // Test with ProcessAllSections = false (the default).
101*9880d681SAndroid Build Coastguard Worker     auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver);
102*9880d681SAndroid Build Coastguard Worker     EXPECT_EQ(DebugSectionSeen, false)
103*9880d681SAndroid Build Coastguard Worker       << "Unexpected debug info section";
104*9880d681SAndroid Build Coastguard Worker     ObjLayer.removeObjectSet(H);
105*9880d681SAndroid Build Coastguard Worker   }
106*9880d681SAndroid Build Coastguard Worker 
107*9880d681SAndroid Build Coastguard Worker   {
108*9880d681SAndroid Build Coastguard Worker     // Test with ProcessAllSections = true.
109*9880d681SAndroid Build Coastguard Worker     ObjLayer.setProcessAllSections(true);
110*9880d681SAndroid Build Coastguard Worker     auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver);
111*9880d681SAndroid Build Coastguard Worker     EXPECT_EQ(DebugSectionSeen, true)
112*9880d681SAndroid Build Coastguard Worker       << "Expected debug info section not seen";
113*9880d681SAndroid Build Coastguard Worker     ObjLayer.removeObjectSet(H);
114*9880d681SAndroid Build Coastguard Worker   }
115*9880d681SAndroid Build Coastguard Worker }
116*9880d681SAndroid Build Coastguard Worker 
TEST_F(ObjectLinkingLayerExecutionTest,NoDuplicateFinalization)117*9880d681SAndroid Build Coastguard Worker TEST_F(ObjectLinkingLayerExecutionTest, NoDuplicateFinalization) {
118*9880d681SAndroid Build Coastguard Worker   if (!TM)
119*9880d681SAndroid Build Coastguard Worker     return;
120*9880d681SAndroid Build Coastguard Worker 
121*9880d681SAndroid Build Coastguard Worker   ObjectLinkingLayer<> ObjLayer;
122*9880d681SAndroid Build Coastguard Worker   SimpleCompiler Compile(*TM);
123*9880d681SAndroid Build Coastguard Worker 
124*9880d681SAndroid Build Coastguard Worker   // Create a pair of modules that will trigger recursive finalization:
125*9880d681SAndroid Build Coastguard Worker   // Module 1:
126*9880d681SAndroid Build Coastguard Worker   //   int bar() { return 42; }
127*9880d681SAndroid Build Coastguard Worker   // Module 2:
128*9880d681SAndroid Build Coastguard Worker   //   int bar();
129*9880d681SAndroid Build Coastguard Worker   //   int foo() { return bar(); }
130*9880d681SAndroid Build Coastguard Worker   //
131*9880d681SAndroid Build Coastguard Worker   // Verify that the memory manager is only finalized once (for Module 2).
132*9880d681SAndroid Build Coastguard Worker   // Failure suggests that finalize is being called on the inner RTDyld
133*9880d681SAndroid Build Coastguard Worker   // instance (for Module 1) which is unsafe, as it will prevent relocation of
134*9880d681SAndroid Build Coastguard Worker   // Module 2.
135*9880d681SAndroid Build Coastguard Worker 
136*9880d681SAndroid Build Coastguard Worker   ModuleBuilder MB1(Context, "", "dummy");
137*9880d681SAndroid Build Coastguard Worker   {
138*9880d681SAndroid Build Coastguard Worker     MB1.getModule()->setDataLayout(TM->createDataLayout());
139*9880d681SAndroid Build Coastguard Worker     Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("bar");
140*9880d681SAndroid Build Coastguard Worker     BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
141*9880d681SAndroid Build Coastguard Worker     IRBuilder<> Builder(BarEntry);
142*9880d681SAndroid Build Coastguard Worker     IntegerType *Int32Ty = IntegerType::get(Context, 32);
143*9880d681SAndroid Build Coastguard Worker     Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
144*9880d681SAndroid Build Coastguard Worker     Builder.CreateRet(FourtyTwo);
145*9880d681SAndroid Build Coastguard Worker   }
146*9880d681SAndroid Build Coastguard Worker 
147*9880d681SAndroid Build Coastguard Worker   auto Obj1 = Compile(*MB1.getModule());
148*9880d681SAndroid Build Coastguard Worker   std::vector<object::ObjectFile*> Obj1Set;
149*9880d681SAndroid Build Coastguard Worker   Obj1Set.push_back(Obj1.getBinary());
150*9880d681SAndroid Build Coastguard Worker 
151*9880d681SAndroid Build Coastguard Worker   ModuleBuilder MB2(Context, "", "dummy");
152*9880d681SAndroid Build Coastguard Worker   {
153*9880d681SAndroid Build Coastguard Worker     MB2.getModule()->setDataLayout(TM->createDataLayout());
154*9880d681SAndroid Build Coastguard Worker     Function *BarDecl = MB2.createFunctionDecl<int32_t(void)>("bar");
155*9880d681SAndroid Build Coastguard Worker     Function *FooImpl = MB2.createFunctionDecl<int32_t(void)>("foo");
156*9880d681SAndroid Build Coastguard Worker     BasicBlock *FooEntry = BasicBlock::Create(Context, "entry", FooImpl);
157*9880d681SAndroid Build Coastguard Worker     IRBuilder<> Builder(FooEntry);
158*9880d681SAndroid Build Coastguard Worker     Builder.CreateRet(Builder.CreateCall(BarDecl));
159*9880d681SAndroid Build Coastguard Worker   }
160*9880d681SAndroid Build Coastguard Worker   auto Obj2 = Compile(*MB2.getModule());
161*9880d681SAndroid Build Coastguard Worker   std::vector<object::ObjectFile*> Obj2Set;
162*9880d681SAndroid Build Coastguard Worker   Obj2Set.push_back(Obj2.getBinary());
163*9880d681SAndroid Build Coastguard Worker 
164*9880d681SAndroid Build Coastguard Worker   auto Resolver =
165*9880d681SAndroid Build Coastguard Worker     createLambdaResolver(
166*9880d681SAndroid Build Coastguard Worker       [&](const std::string &Name) {
167*9880d681SAndroid Build Coastguard Worker         if (auto Sym = ObjLayer.findSymbol(Name, true))
168*9880d681SAndroid Build Coastguard Worker           return Sym.toRuntimeDyldSymbol();
169*9880d681SAndroid Build Coastguard Worker         return RuntimeDyld::SymbolInfo(nullptr);
170*9880d681SAndroid Build Coastguard Worker       },
171*9880d681SAndroid Build Coastguard Worker       [](const std::string &Name) {
172*9880d681SAndroid Build Coastguard Worker         return RuntimeDyld::SymbolInfo(nullptr);
173*9880d681SAndroid Build Coastguard Worker       });
174*9880d681SAndroid Build Coastguard Worker 
175*9880d681SAndroid Build Coastguard Worker   SectionMemoryManagerWrapper SMMW;
176*9880d681SAndroid Build Coastguard Worker   ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &*Resolver);
177*9880d681SAndroid Build Coastguard Worker   auto H = ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &*Resolver);
178*9880d681SAndroid Build Coastguard Worker   ObjLayer.emitAndFinalize(H);
179*9880d681SAndroid Build Coastguard Worker 
180*9880d681SAndroid Build Coastguard Worker   // Finalization of module 2 should trigger finalization of module 1.
181*9880d681SAndroid Build Coastguard Worker   // Verify that finalize on SMMW is only called once.
182*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(SMMW.FinalizationCount, 1)
183*9880d681SAndroid Build Coastguard Worker       << "Extra call to finalize";
184*9880d681SAndroid Build Coastguard Worker }
185*9880d681SAndroid Build Coastguard Worker 
TEST_F(ObjectLinkingLayerExecutionTest,NoPrematureAllocation)186*9880d681SAndroid Build Coastguard Worker TEST_F(ObjectLinkingLayerExecutionTest, NoPrematureAllocation) {
187*9880d681SAndroid Build Coastguard Worker   if (!TM)
188*9880d681SAndroid Build Coastguard Worker     return;
189*9880d681SAndroid Build Coastguard Worker 
190*9880d681SAndroid Build Coastguard Worker   ObjectLinkingLayer<> ObjLayer;
191*9880d681SAndroid Build Coastguard Worker   SimpleCompiler Compile(*TM);
192*9880d681SAndroid Build Coastguard Worker 
193*9880d681SAndroid Build Coastguard Worker   // Create a pair of unrelated modules:
194*9880d681SAndroid Build Coastguard Worker   //
195*9880d681SAndroid Build Coastguard Worker   // Module 1:
196*9880d681SAndroid Build Coastguard Worker   //   int foo() { return 42; }
197*9880d681SAndroid Build Coastguard Worker   // Module 2:
198*9880d681SAndroid Build Coastguard Worker   //   int bar() { return 7; }
199*9880d681SAndroid Build Coastguard Worker   //
200*9880d681SAndroid Build Coastguard Worker   // Both modules will share a memory manager. We want to verify that the
201*9880d681SAndroid Build Coastguard Worker   // second object is not loaded before the first one is finalized. To do this
202*9880d681SAndroid Build Coastguard Worker   // in a portable way, we abuse the
203*9880d681SAndroid Build Coastguard Worker   // RuntimeDyld::MemoryManager::needsToReserveAllocationSpace hook, which is
204*9880d681SAndroid Build Coastguard Worker   // called once per object before any sections are allocated.
205*9880d681SAndroid Build Coastguard Worker 
206*9880d681SAndroid Build Coastguard Worker   ModuleBuilder MB1(Context, "", "dummy");
207*9880d681SAndroid Build Coastguard Worker   {
208*9880d681SAndroid Build Coastguard Worker     MB1.getModule()->setDataLayout(TM->createDataLayout());
209*9880d681SAndroid Build Coastguard Worker     Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("foo");
210*9880d681SAndroid Build Coastguard Worker     BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
211*9880d681SAndroid Build Coastguard Worker     IRBuilder<> Builder(BarEntry);
212*9880d681SAndroid Build Coastguard Worker     IntegerType *Int32Ty = IntegerType::get(Context, 32);
213*9880d681SAndroid Build Coastguard Worker     Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
214*9880d681SAndroid Build Coastguard Worker     Builder.CreateRet(FourtyTwo);
215*9880d681SAndroid Build Coastguard Worker   }
216*9880d681SAndroid Build Coastguard Worker 
217*9880d681SAndroid Build Coastguard Worker   auto Obj1 = Compile(*MB1.getModule());
218*9880d681SAndroid Build Coastguard Worker   std::vector<object::ObjectFile*> Obj1Set;
219*9880d681SAndroid Build Coastguard Worker   Obj1Set.push_back(Obj1.getBinary());
220*9880d681SAndroid Build Coastguard Worker 
221*9880d681SAndroid Build Coastguard Worker   ModuleBuilder MB2(Context, "", "dummy");
222*9880d681SAndroid Build Coastguard Worker   {
223*9880d681SAndroid Build Coastguard Worker     MB2.getModule()->setDataLayout(TM->createDataLayout());
224*9880d681SAndroid Build Coastguard Worker     Function *BarImpl = MB2.createFunctionDecl<int32_t(void)>("bar");
225*9880d681SAndroid Build Coastguard Worker     BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
226*9880d681SAndroid Build Coastguard Worker     IRBuilder<> Builder(BarEntry);
227*9880d681SAndroid Build Coastguard Worker     IntegerType *Int32Ty = IntegerType::get(Context, 32);
228*9880d681SAndroid Build Coastguard Worker     Value *Seven = ConstantInt::getSigned(Int32Ty, 7);
229*9880d681SAndroid Build Coastguard Worker     Builder.CreateRet(Seven);
230*9880d681SAndroid Build Coastguard Worker   }
231*9880d681SAndroid Build Coastguard Worker   auto Obj2 = Compile(*MB2.getModule());
232*9880d681SAndroid Build Coastguard Worker   std::vector<object::ObjectFile*> Obj2Set;
233*9880d681SAndroid Build Coastguard Worker   Obj2Set.push_back(Obj2.getBinary());
234*9880d681SAndroid Build Coastguard Worker 
235*9880d681SAndroid Build Coastguard Worker   SectionMemoryManagerWrapper SMMW;
236*9880d681SAndroid Build Coastguard Worker   NullResolver NR;
237*9880d681SAndroid Build Coastguard Worker   auto H = ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &NR);
238*9880d681SAndroid Build Coastguard Worker   ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &NR);
239*9880d681SAndroid Build Coastguard Worker   ObjLayer.emitAndFinalize(H);
240*9880d681SAndroid Build Coastguard Worker 
241*9880d681SAndroid Build Coastguard Worker   // Only one call to needsToReserveAllocationSpace should have been made.
242*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(SMMW.NeedsToReserveAllocationSpaceCount, 1)
243*9880d681SAndroid Build Coastguard Worker       << "More than one call to needsToReserveAllocationSpace "
244*9880d681SAndroid Build Coastguard Worker          "(multiple unrelated objects loaded prior to finalization)";
245*9880d681SAndroid Build Coastguard Worker }
246*9880d681SAndroid Build Coastguard Worker 
247*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
248