blob: d7c0b74670c32bf42d9d0bbdf8b8f10d8c9ce302 [file] [log] [blame]
Lang Hames5f7fcef2015-10-29 03:53:42 +00001//===-- 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
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"
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
20using namespace llvm;
21using namespace llvm::orc;
22
23namespace {
24
Lang Hames859d73c2016-01-09 19:50:40 +000025class ObjectLinkingLayerExecutionTest : public testing::Test,
26 public OrcExecutionTest {
27};
28
Lang Hames5f7fcef2015-10-29 03:53:42 +000029TEST(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
Lang Hames859d73c2016-01-09 19:50:40 +000099
100TEST_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
Lang Hames5f7fcef2015-10-29 03:53:42 +0000176}