IR: de-duplicate two CmpInst routines (NFC) (#116866)
[llvm-project.git] / llvm / unittests / ExecutionEngine / Orc / RTDyldObjectLinkingLayerTest.cpp
blob82d6968ea9874e93ebea338c4b5bf6f3aca56183
1 //===--- RTDyldObjectLinkingLayerTest.cpp - RTDyld linking layer tests ---===//
2 //
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
6 //
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/RTDyldObjectLinkingLayer.h"
14 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
15 #include "llvm/IR/Constants.h"
16 #include "llvm/IR/LLVMContext.h"
17 #include "gtest/gtest.h"
18 #include <string>
20 using namespace llvm;
21 using namespace llvm::orc;
23 namespace {
25 // Returns whether a non-alloc section was passed to the memory manager.
26 static bool testSetProcessAllSections(std::unique_ptr<MemoryBuffer> Obj,
27 bool ProcessAllSections) {
28 class MemoryManagerWrapper : public SectionMemoryManager {
29 public:
30 MemoryManagerWrapper(bool &NonAllocSeen) : NonAllocSeen(NonAllocSeen) {}
31 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
32 unsigned SectionID, StringRef SectionName,
33 bool IsReadOnly) override {
34 // We check for ".note.GNU-stack" here because it is currently the only
35 // non-alloc section seen in the module. If this changes in future any
36 // other non-alloc section would do here.
37 if (SectionName == ".note.GNU-stack")
38 NonAllocSeen = true;
39 return SectionMemoryManager::allocateDataSection(
40 Size, Alignment, SectionID, SectionName, IsReadOnly);
43 private:
44 bool &NonAllocSeen;
47 bool NonAllocSectionSeen = false;
49 ExecutionSession ES(std::make_unique<UnsupportedExecutorProcessControl>());
50 auto &JD = ES.createBareJITDylib("main");
51 auto Foo = ES.intern("foo");
53 RTDyldObjectLinkingLayer ObjLayer(ES, [&NonAllocSectionSeen]() {
54 return std::make_unique<MemoryManagerWrapper>(NonAllocSectionSeen);
55 });
57 auto OnResolveDoNothing = [](Expected<SymbolMap> R) {
58 cantFail(std::move(R));
61 ObjLayer.setProcessAllSections(ProcessAllSections);
62 cantFail(ObjLayer.add(JD, std::move(Obj)));
63 ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
64 SymbolLookupSet(Foo), SymbolState::Resolved, OnResolveDoNothing,
65 NoDependenciesToRegister);
67 if (auto Err = ES.endSession())
68 ES.reportError(std::move(Err));
70 return NonAllocSectionSeen;
73 TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) {
74 LLVMContext Context;
75 auto M = std::make_unique<Module>("", Context);
76 M->setTargetTriple("x86_64-unknown-linux-gnu");
78 // These values are only here to ensure that the module is non-empty.
79 // They are no longer relevant to the test.
80 Constant *StrConstant = ConstantDataArray::getString(Context, "forty-two");
81 auto *GV =
82 new GlobalVariable(*M, StrConstant->getType(), true,
83 GlobalValue::ExternalLinkage, StrConstant, "foo");
84 GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
85 GV->setAlignment(Align(1));
87 // Initialize the native target in case this is the first unit test
88 // to try to build a TM.
89 OrcNativeTarget::initialize();
90 std::unique_ptr<TargetMachine> TM(EngineBuilder().selectTarget(
91 Triple(M->getTargetTriple()), "", "", SmallVector<std::string, 1>()));
92 if (!TM)
93 GTEST_SKIP();
95 auto Obj = cantFail(SimpleCompiler(*TM)(*M));
97 EXPECT_FALSE(testSetProcessAllSections(
98 MemoryBuffer::getMemBufferCopy(Obj->getBuffer()), false))
99 << "Non-alloc section seen despite ProcessAllSections being false";
100 EXPECT_TRUE(testSetProcessAllSections(std::move(Obj), true))
101 << "Expected to see non-alloc section when ProcessAllSections is true";
104 TEST(RTDyldObjectLinkingLayerTest, TestOverrideObjectFlags) {
106 OrcNativeTarget::initialize();
108 std::unique_ptr<TargetMachine> TM(
109 EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "",
110 SmallVector<std::string, 1>()));
112 if (!TM)
113 GTEST_SKIP();
115 // Our compiler is going to modify symbol visibility settings without telling
116 // ORC. This will test our ability to override the flags later.
117 class FunkySimpleCompiler : public SimpleCompiler {
118 public:
119 FunkySimpleCompiler(TargetMachine &TM) : SimpleCompiler(TM) {}
121 Expected<CompileResult> operator()(Module &M) override {
122 auto *Foo = M.getFunction("foo");
123 assert(Foo && "Expected function Foo not found");
124 Foo->setVisibility(GlobalValue::HiddenVisibility);
125 return SimpleCompiler::operator()(M);
129 // Create a module with two void() functions: foo and bar.
130 ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
131 ThreadSafeModule M;
133 ModuleBuilder MB(*TSCtx.getContext(), TM->getTargetTriple().str(), "dummy");
134 MB.getModule()->setDataLayout(TM->createDataLayout());
136 Function *FooImpl = MB.createFunctionDecl(
137 FunctionType::get(Type::getVoidTy(*TSCtx.getContext()), {}, false),
138 "foo");
139 BasicBlock *FooEntry =
140 BasicBlock::Create(*TSCtx.getContext(), "entry", FooImpl);
141 IRBuilder<> B1(FooEntry);
142 B1.CreateRetVoid();
144 Function *BarImpl = MB.createFunctionDecl(
145 FunctionType::get(Type::getVoidTy(*TSCtx.getContext()), {}, false),
146 "bar");
147 BasicBlock *BarEntry =
148 BasicBlock::Create(*TSCtx.getContext(), "entry", BarImpl);
149 IRBuilder<> B2(BarEntry);
150 B2.CreateRetVoid();
152 M = ThreadSafeModule(MB.takeModule(), std::move(TSCtx));
155 // Create a simple stack and set the override flags option.
156 ExecutionSession ES{std::make_unique<UnsupportedExecutorProcessControl>()};
157 auto &JD = ES.createBareJITDylib("main");
158 auto Foo = ES.intern("foo");
159 RTDyldObjectLinkingLayer ObjLayer(
160 ES, []() { return std::make_unique<SectionMemoryManager>(); });
161 IRCompileLayer CompileLayer(ES, ObjLayer,
162 std::make_unique<FunkySimpleCompiler>(*TM));
164 ObjLayer.setOverrideObjectFlagsWithResponsibilityFlags(true);
166 cantFail(CompileLayer.add(JD, std::move(M)));
167 ES.lookup(
168 LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo),
169 SymbolState::Resolved,
170 [](Expected<SymbolMap> R) { cantFail(std::move(R)); },
171 NoDependenciesToRegister);
173 if (auto Err = ES.endSession())
174 ES.reportError(std::move(Err));
177 TEST(RTDyldObjectLinkingLayerTest, TestAutoClaimResponsibilityForSymbols) {
179 OrcNativeTarget::initialize();
181 std::unique_ptr<TargetMachine> TM(
182 EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "",
183 SmallVector<std::string, 1>()));
185 if (!TM)
186 GTEST_SKIP();
188 // Our compiler is going to add a new symbol without telling ORC.
189 // This will test our ability to auto-claim responsibility later.
190 class FunkySimpleCompiler : public SimpleCompiler {
191 public:
192 FunkySimpleCompiler(TargetMachine &TM) : SimpleCompiler(TM) {}
194 Expected<CompileResult> operator()(Module &M) override {
195 Function *BarImpl = Function::Create(
196 FunctionType::get(Type::getVoidTy(M.getContext()), {}, false),
197 GlobalValue::ExternalLinkage, "bar", &M);
198 BasicBlock *BarEntry =
199 BasicBlock::Create(M.getContext(), "entry", BarImpl);
200 IRBuilder<> B(BarEntry);
201 B.CreateRetVoid();
203 return SimpleCompiler::operator()(M);
207 // Create a module with two void() functions: foo and bar.
208 ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
209 ThreadSafeModule M;
211 ModuleBuilder MB(*TSCtx.getContext(), TM->getTargetTriple().str(), "dummy");
212 MB.getModule()->setDataLayout(TM->createDataLayout());
214 Function *FooImpl = MB.createFunctionDecl(
215 FunctionType::get(Type::getVoidTy(*TSCtx.getContext()), {}, false),
216 "foo");
217 BasicBlock *FooEntry =
218 BasicBlock::Create(*TSCtx.getContext(), "entry", FooImpl);
219 IRBuilder<> B(FooEntry);
220 B.CreateRetVoid();
222 M = ThreadSafeModule(MB.takeModule(), std::move(TSCtx));
225 // Create a simple stack and set the override flags option.
226 ExecutionSession ES{std::make_unique<UnsupportedExecutorProcessControl>()};
227 auto &JD = ES.createBareJITDylib("main");
228 auto Foo = ES.intern("foo");
229 RTDyldObjectLinkingLayer ObjLayer(
230 ES, []() { return std::make_unique<SectionMemoryManager>(); });
231 IRCompileLayer CompileLayer(ES, ObjLayer,
232 std::make_unique<FunkySimpleCompiler>(*TM));
234 ObjLayer.setAutoClaimResponsibilityForObjectSymbols(true);
236 cantFail(CompileLayer.add(JD, std::move(M)));
237 ES.lookup(
238 LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo),
239 SymbolState::Resolved,
240 [](Expected<SymbolMap> R) { cantFail(std::move(R)); },
241 NoDependenciesToRegister);
243 if (auto Err = ES.endSession())
244 ES.reportError(std::move(Err));
247 } // end anonymous namespace