[Orc][RuntimeDyld] Prevent duplicate calls to finalizeMemory on shared memory
[oota-llvm.git] / unittests / ExecutionEngine / Orc / ObjectLinkingLayerTest.cpp
1 //===-- ObjectLinkingLayerTest.cpp - Unit tests for object linking layer --===//
2 //
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
10 #include "OrcTestCommon.h"
11 #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"
15 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
16 #include "llvm/IR/Constants.h"
17 #include "llvm/IR/LLVMContext.h"
18 #include "gtest/gtest.h"
19
20 using namespace llvm;
21 using namespace llvm::orc;
22
23 namespace {
24
25 class ObjectLinkingLayerExecutionTest : public testing::Test,
26                                         public OrcExecutionTest {
27 };
28
29 TEST(ObjectLinkingLayerTest, TestSetProcessAllSections) {
30
31   class SectionMemoryManagerWrapper : public SectionMemoryManager {
32   public:
33     SectionMemoryManagerWrapper(bool &DebugSeen) : DebugSeen(DebugSeen) {}
34     uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
35                                  unsigned SectionID,
36                                  StringRef SectionName,
37                                  bool IsReadOnly) override {
38       if (SectionName == ".debug_str")
39         DebugSeen = true;
40       return SectionMemoryManager::allocateDataSection(Size, Alignment,
41                                                          SectionID,
42                                                          SectionName,
43                                                          IsReadOnly);
44     }
45   private:
46     bool DebugSeen;
47   };
48
49   ObjectLinkingLayer<> ObjLayer;
50
51   auto M = llvm::make_unique<Module>("", getGlobalContext());
52   M->setTargetTriple("x86_64-unknown-linux-gnu");
53   Type *Int32Ty = IntegerType::get(getGlobalContext(), 32);
54   GlobalVariable *GV =
55     new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage,
56                          ConstantInt::get(Int32Ty, 42), "foo");
57
58   GV->setSection(".debug_str");
59
60   std::unique_ptr<TargetMachine> TM(
61     EngineBuilder().selectTarget(Triple(M->getTargetTriple()), "", "",
62                                  SmallVector<std::string, 1>()));
63   if (!TM)
64     return;
65
66   auto OwningObj = SimpleCompiler(*TM)(*M);
67   std::vector<object::ObjectFile*> Objs;
68   Objs.push_back(OwningObj.getBinary());
69
70   bool DebugSectionSeen = false;
71   SectionMemoryManagerWrapper SMMW(DebugSectionSeen);
72   auto Resolver =
73     createLambdaResolver(
74       [](const std::string &Name) {
75         return RuntimeDyld::SymbolInfo(nullptr);
76       },
77       [](const std::string &Name) {
78         return RuntimeDyld::SymbolInfo(nullptr);
79       });
80
81   {
82     // Test with ProcessAllSections = false (the default).
83     auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver);
84     EXPECT_EQ(DebugSectionSeen, false)
85       << "Unexpected debug info section";
86     ObjLayer.removeObjectSet(H);
87   }
88
89   {
90     // Test with ProcessAllSections = true.
91     ObjLayer.setProcessAllSections(true);
92     auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver);
93     EXPECT_EQ(DebugSectionSeen, true)
94       << "Expected debug info section not seen";
95     ObjLayer.removeObjectSet(H);
96   }
97 }
98
99
100 TEST_F(ObjectLinkingLayerExecutionTest, NoDuplicateFinalization) {
101
102   if (!TM)
103     return;
104
105   class SectionMemoryManagerWrapper : public SectionMemoryManager {
106   public:
107     int FinalizationCount = 0;
108     bool finalizeMemory(std::string *ErrMsg = 0) override {
109       ++FinalizationCount;
110       return SectionMemoryManager::finalizeMemory(ErrMsg);
111     }
112   };
113
114   ObjectLinkingLayer<> ObjLayer;
115   SimpleCompiler Compile(*TM);
116
117   // Create a pair of modules that will trigger recursive finalization:
118   // Module 1:
119   //   int bar() { return 42; }
120   // Module 2:
121   //   int bar();
122   //   int foo() { return bar(); }
123
124   ModuleBuilder MB1(getGlobalContext(), "", "dummy");
125   {
126     MB1.getModule()->setDataLayout(TM->createDataLayout());
127     Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("bar");
128     BasicBlock *BarEntry = BasicBlock::Create(getGlobalContext(), "entry",
129                                               BarImpl);
130     IRBuilder<> Builder(BarEntry);
131     IntegerType *Int32Ty = IntegerType::get(getGlobalContext(), 32);
132     Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
133     Builder.CreateRet(FourtyTwo);
134   }
135
136   auto Obj1 = Compile(*MB1.getModule());
137   std::vector<object::ObjectFile*> Obj1Set;
138   Obj1Set.push_back(Obj1.getBinary());
139
140   ModuleBuilder MB2(getGlobalContext(), "", "dummy");
141   {
142     MB2.getModule()->setDataLayout(TM->createDataLayout());
143     Function *BarDecl = MB2.createFunctionDecl<int32_t(void)>("bar");
144     Function *FooImpl = MB2.createFunctionDecl<int32_t(void)>("foo");
145     BasicBlock *FooEntry = BasicBlock::Create(getGlobalContext(), "entry",
146                                               FooImpl);
147     IRBuilder<> Builder(FooEntry);
148     Builder.CreateRet(Builder.CreateCall(BarDecl));
149   }
150   auto Obj2 = Compile(*MB2.getModule());
151   std::vector<object::ObjectFile*> Obj2Set;
152   Obj2Set.push_back(Obj2.getBinary());
153
154   auto Resolver =
155     createLambdaResolver(
156       [&](const std::string &Name) {
157         if (auto Sym = ObjLayer.findSymbol(Name, true))
158           return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags());
159         return RuntimeDyld::SymbolInfo(nullptr);
160       },
161       [](const std::string &Name) {
162         return RuntimeDyld::SymbolInfo(nullptr);
163       });
164
165   SectionMemoryManagerWrapper SMMW;
166   ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &*Resolver);
167   auto H = ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &*Resolver);
168   ObjLayer.emitAndFinalize(H);
169
170   // Finalization of module 2 should trigger finalization of module 1.
171   // Verify that finalize on SMMW is only called once.
172   EXPECT_EQ(SMMW.FinalizationCount, 1)
173       << "Extra call to finalize";
174 }
175
176 }