1 //===--- RTDyldObjectLinkingLayerTest.cpp - RTDyld linking layer tests ---===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "OrcTestCommon.h"
10 #include "llvm/ExecutionEngine/ExecutionEngine.h"
11 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
12 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
13 #include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
14 #include "llvm/ExecutionEngine/Orc/Legacy.h"
15 #include "llvm/ExecutionEngine/Orc/NullResolver.h"
16 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
17 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
18 #include "llvm/IR/Constants.h"
19 #include "llvm/IR/LLVMContext.h"
20 #include "gtest/gtest.h"
23 using namespace llvm::orc
;
27 class RTDyldObjectLinkingLayerExecutionTest
: public testing::Test
,
28 public OrcExecutionTest
{};
30 // Adds an object with a debug section to RuntimeDyld and then returns whether
31 // the debug section was passed to the memory manager.
32 static bool testSetProcessAllSections(std::unique_ptr
<MemoryBuffer
> Obj
,
33 bool ProcessAllSections
) {
34 class MemoryManagerWrapper
: public SectionMemoryManager
{
36 MemoryManagerWrapper(bool &DebugSeen
) : DebugSeen(DebugSeen
) {}
37 uint8_t *allocateDataSection(uintptr_t Size
, unsigned Alignment
,
38 unsigned SectionID
, StringRef SectionName
,
39 bool IsReadOnly
) override
{
40 if (SectionName
== ".debug_str")
42 return SectionMemoryManager::allocateDataSection(
43 Size
, Alignment
, SectionID
, SectionName
, IsReadOnly
);
50 bool DebugSectionSeen
= false;
53 auto &JD
= ES
.createJITDylib("main");
54 auto Foo
= ES
.intern("foo");
56 RTDyldObjectLinkingLayer
ObjLayer(ES
, [&DebugSectionSeen
]() {
57 return llvm::make_unique
<MemoryManagerWrapper
>(DebugSectionSeen
);
60 auto OnResolveDoNothing
= [](Expected
<SymbolMap
> R
) {
61 cantFail(std::move(R
));
64 auto OnReadyDoNothing
= [](Error Err
) { cantFail(std::move(Err
)); };
66 ObjLayer
.setProcessAllSections(ProcessAllSections
);
67 cantFail(ObjLayer
.add(JD
, std::move(Obj
), ES
.allocateVModule()));
68 ES
.lookup(JITDylibSearchList({{&JD
, false}}), {Foo
}, OnResolveDoNothing
,
69 OnReadyDoNothing
, NoDependenciesToRegister
);
70 return DebugSectionSeen
;
73 TEST(RTDyldObjectLinkingLayerTest
, TestSetProcessAllSections
) {
75 auto M
= llvm::make_unique
<Module
>("", Context
);
76 M
->setTargetTriple("x86_64-unknown-linux-gnu");
77 Type
*Int32Ty
= IntegerType::get(Context
, 32);
79 new GlobalVariable(*M
, Int32Ty
, false, GlobalValue::ExternalLinkage
,
80 ConstantInt::get(Int32Ty
, 42), "foo");
82 GV
->setSection(".debug_str");
84 // Initialize the native target in case this is the first unit test
85 // to try to build a TM.
86 OrcNativeTarget::initialize();
87 std::unique_ptr
<TargetMachine
> TM(EngineBuilder().selectTarget(
88 Triple(M
->getTargetTriple()), "", "", SmallVector
<std::string
, 1>()));
92 auto Obj
= SimpleCompiler(*TM
)(*M
);
94 EXPECT_FALSE(testSetProcessAllSections(
95 MemoryBuffer::getMemBufferCopy(Obj
->getBuffer()), false))
96 << "Debug section seen despite ProcessAllSections being false";
97 EXPECT_TRUE(testSetProcessAllSections(std::move(Obj
), true))
98 << "Expected to see debug section when ProcessAllSections is true";
101 TEST(RTDyldObjectLinkingLayerTest
, TestOverrideObjectFlags
) {
103 OrcNativeTarget::initialize();
105 std::unique_ptr
<TargetMachine
> TM(
106 EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "",
107 SmallVector
<std::string
, 1>()));
112 // Our compiler is going to modify symbol visibility settings without telling
113 // ORC. This will test our ability to override the flags later.
114 class FunkySimpleCompiler
: public SimpleCompiler
{
116 FunkySimpleCompiler(TargetMachine
&TM
) : SimpleCompiler(TM
) {}
118 CompileResult
operator()(Module
&M
) {
119 auto *Foo
= M
.getFunction("foo");
120 assert(Foo
&& "Expected function Foo not found");
121 Foo
->setVisibility(GlobalValue::HiddenVisibility
);
122 return SimpleCompiler::operator()(M
);
126 // Create a module with two void() functions: foo and bar.
127 ThreadSafeContext
TSCtx(llvm::make_unique
<LLVMContext
>());
130 ModuleBuilder
MB(*TSCtx
.getContext(), TM
->getTargetTriple().str(), "dummy");
131 MB
.getModule()->setDataLayout(TM
->createDataLayout());
133 Function
*FooImpl
= MB
.createFunctionDecl(
134 FunctionType::get(Type::getVoidTy(*TSCtx
.getContext()), {}, false),
136 BasicBlock
*FooEntry
=
137 BasicBlock::Create(*TSCtx
.getContext(), "entry", FooImpl
);
138 IRBuilder
<> B1(FooEntry
);
141 Function
*BarImpl
= MB
.createFunctionDecl(
142 FunctionType::get(Type::getVoidTy(*TSCtx
.getContext()), {}, false),
144 BasicBlock
*BarEntry
=
145 BasicBlock::Create(*TSCtx
.getContext(), "entry", BarImpl
);
146 IRBuilder
<> B2(BarEntry
);
149 M
= ThreadSafeModule(MB
.takeModule(), std::move(TSCtx
));
152 // Create a simple stack and set the override flags option.
154 auto &JD
= ES
.createJITDylib("main");
155 auto Foo
= ES
.intern("foo");
156 RTDyldObjectLinkingLayer
ObjLayer(
157 ES
, []() { return llvm::make_unique
<SectionMemoryManager
>(); });
158 IRCompileLayer
CompileLayer(ES
, ObjLayer
, FunkySimpleCompiler(*TM
));
160 ObjLayer
.setOverrideObjectFlagsWithResponsibilityFlags(true);
162 cantFail(CompileLayer
.add(JD
, std::move(M
), ES
.allocateVModule()));
163 ES
.lookup(JITDylibSearchList({{&JD
, false}}), {Foo
},
164 [](Expected
<SymbolMap
> R
) { cantFail(std::move(R
)); },
165 [](Error Err
) { cantFail(std::move(Err
)); },
166 NoDependenciesToRegister
);
169 TEST(RTDyldObjectLinkingLayerTest
, TestAutoClaimResponsibilityForSymbols
) {
171 OrcNativeTarget::initialize();
173 std::unique_ptr
<TargetMachine
> TM(
174 EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "",
175 SmallVector
<std::string
, 1>()));
180 // Our compiler is going to add a new symbol without telling ORC.
181 // This will test our ability to auto-claim responsibility later.
182 class FunkySimpleCompiler
: public SimpleCompiler
{
184 FunkySimpleCompiler(TargetMachine
&TM
) : SimpleCompiler(TM
) {}
186 CompileResult
operator()(Module
&M
) {
187 Function
*BarImpl
= Function::Create(
188 FunctionType::get(Type::getVoidTy(M
.getContext()), {}, false),
189 GlobalValue::ExternalLinkage
, "bar", &M
);
190 BasicBlock
*BarEntry
=
191 BasicBlock::Create(M
.getContext(), "entry", BarImpl
);
192 IRBuilder
<> B(BarEntry
);
195 return SimpleCompiler::operator()(M
);
199 // Create a module with two void() functions: foo and bar.
200 ThreadSafeContext
TSCtx(llvm::make_unique
<LLVMContext
>());
203 ModuleBuilder
MB(*TSCtx
.getContext(), TM
->getTargetTriple().str(), "dummy");
204 MB
.getModule()->setDataLayout(TM
->createDataLayout());
206 Function
*FooImpl
= MB
.createFunctionDecl(
207 FunctionType::get(Type::getVoidTy(*TSCtx
.getContext()), {}, false),
209 BasicBlock
*FooEntry
=
210 BasicBlock::Create(*TSCtx
.getContext(), "entry", FooImpl
);
211 IRBuilder
<> B(FooEntry
);
214 M
= ThreadSafeModule(MB
.takeModule(), std::move(TSCtx
));
217 // Create a simple stack and set the override flags option.
219 auto &JD
= ES
.createJITDylib("main");
220 auto Foo
= ES
.intern("foo");
221 RTDyldObjectLinkingLayer
ObjLayer(
222 ES
, []() { return llvm::make_unique
<SectionMemoryManager
>(); });
223 IRCompileLayer
CompileLayer(ES
, ObjLayer
, FunkySimpleCompiler(*TM
));
225 ObjLayer
.setAutoClaimResponsibilityForObjectSymbols(true);
227 cantFail(CompileLayer
.add(JD
, std::move(M
), ES
.allocateVModule()));
228 ES
.lookup(JITDylibSearchList({{&JD
, false}}), {Foo
},
229 [](Expected
<SymbolMap
> R
) { cantFail(std::move(R
)); },
230 [](Error Err
) { cantFail(std::move(Err
)); },
231 NoDependenciesToRegister
);
234 } // end anonymous namespace