blob: 284a1e37f103af26ad5502ce2c290f0f3942eac9 [file] [log] [blame]
Lang Hamesdc4260d2015-04-20 20:41:45 +00001//===------ OrcTestCommon.h - Utilities for Orc Unit Tests ------*- C++ -*-===//
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// Common utilities for the Orc unit tests.
11//
12//===----------------------------------------------------------------------===//
13
14
15#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_ORC_ORCTESTCOMMON_H
16#define LLVM_UNITTESTS_EXECUTIONENGINE_ORC_ORCTESTCOMMON_H
17
Chandler Carruth9a67b072017-06-06 11:06:56 +000018#include "llvm/ExecutionEngine/ExecutionEngine.h"
19#include "llvm/ExecutionEngine/JITSymbol.h"
Lang Hamesa95b0df2018-03-28 03:41:45 +000020#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
Lang Hamesdc4260d2015-04-20 20:41:45 +000021#include "llvm/IR/Function.h"
22#include "llvm/IR/IRBuilder.h"
23#include "llvm/IR/LLVMContext.h"
24#include "llvm/IR/Module.h"
25#include "llvm/IR/TypeBuilder.h"
Lang Hames859d73c2016-01-09 19:50:40 +000026#include "llvm/Object/ObjectFile.h"
Lang Hamesa95b0df2018-03-28 03:41:45 +000027#include "llvm/Support/TargetRegistry.h"
Lang Hamesfd0c1e712018-07-20 18:31:50 +000028#include "llvm/Support/TargetSelect.h"
29#include "gtest/gtest.h"
30
Lang Hamesdc4260d2015-04-20 20:41:45 +000031#include <memory>
32
33namespace llvm {
34
Lang Hamesfd0c1e712018-07-20 18:31:50 +000035namespace orc {
36// CoreAPIsStandardTest that saves a bunch of boilerplate by providing the
37// following:
38//
39// (1) ES -- An ExecutionSession
40// (2) Foo, Bar, Baz, Qux -- SymbolStringPtrs for strings "foo", "bar", "baz",
41// and "qux" respectively.
42// (3) FooAddr, BarAddr, BazAddr, QuxAddr -- Dummy addresses. Guaranteed
43// distinct and non-null.
44// (4) FooSym, BarSym, BazSym, QuxSym -- JITEvaluatedSymbols with FooAddr,
45// BarAddr, BazAddr, and QuxAddr respectively. All with default strong,
46// linkage and non-hidden visibility.
Lang Hamesd5f56c52018-08-17 21:18:18 +000047// (5) V -- A JITDylib associated with ES.
Lang Hamesfd0c1e712018-07-20 18:31:50 +000048class CoreAPIsBasedStandardTest : public testing::Test {
Lang Hamesfd0c1e712018-07-20 18:31:50 +000049protected:
Lang Hames13014d32018-09-12 21:48:59 +000050 std::shared_ptr<SymbolStringPool> SSP = std::make_shared<SymbolStringPool>();
51 ExecutionSession ES{SSP};
Lang Hamesd5f56c52018-08-17 21:18:18 +000052 JITDylib &JD = ES.createJITDylib("JD");
Lang Hames71d781c2018-09-30 23:18:24 +000053 SymbolStringPtr Foo = ES.intern("foo");
54 SymbolStringPtr Bar = ES.intern("bar");
55 SymbolStringPtr Baz = ES.intern("baz");
56 SymbolStringPtr Qux = ES.intern("qux");
Lang Hamesfd0c1e712018-07-20 18:31:50 +000057 static const JITTargetAddress FooAddr = 1U;
58 static const JITTargetAddress BarAddr = 2U;
59 static const JITTargetAddress BazAddr = 3U;
60 static const JITTargetAddress QuxAddr = 4U;
61 JITEvaluatedSymbol FooSym =
62 JITEvaluatedSymbol(FooAddr, JITSymbolFlags::Exported);
63 JITEvaluatedSymbol BarSym =
64 JITEvaluatedSymbol(BarAddr, JITSymbolFlags::Exported);
65 JITEvaluatedSymbol BazSym =
66 JITEvaluatedSymbol(BazAddr, JITSymbolFlags::Exported);
67 JITEvaluatedSymbol QuxSym =
68 JITEvaluatedSymbol(QuxAddr, JITSymbolFlags::Exported);
69};
70
71} // end namespace orc
72
Lang Hamesd22bade2017-04-04 17:03:49 +000073class OrcNativeTarget {
Lang Hames130a7c42015-10-28 02:40:04 +000074public:
Lang Hamesd22bade2017-04-04 17:03:49 +000075 static void initialize() {
Lang Hames130a7c42015-10-28 02:40:04 +000076 if (!NativeTargetInitialized) {
77 InitializeNativeTarget();
78 InitializeNativeTargetAsmParser();
79 InitializeNativeTargetAsmPrinter();
80 NativeTargetInitialized = true;
81 }
Lang Hamesd22bade2017-04-04 17:03:49 +000082 }
83
84private:
85 static bool NativeTargetInitialized;
86};
87
Lang Hamesc1275e72018-09-26 04:18:30 +000088class SimpleMaterializationUnit : public orc::MaterializationUnit {
89public:
90 using MaterializeFunction =
91 std::function<void(orc::MaterializationResponsibility)>;
92 using DiscardFunction =
93 std::function<void(const orc::JITDylib &, orc::SymbolStringPtr)>;
94 using DestructorFunction = std::function<void()>;
95
96 SimpleMaterializationUnit(
97 orc::SymbolFlagsMap SymbolFlags, MaterializeFunction Materialize,
98 DiscardFunction Discard = DiscardFunction(),
99 DestructorFunction Destructor = DestructorFunction())
100 : MaterializationUnit(std::move(SymbolFlags)),
101 Materialize(std::move(Materialize)), Discard(std::move(Discard)),
102 Destructor(std::move(Destructor)) {}
103
104 ~SimpleMaterializationUnit() override {
105 if (Destructor)
106 Destructor();
107 }
108
Lang Hames53e0df12018-09-28 15:09:14 +0000109 StringRef getName() const override { return "<Simple>"; }
110
Lang Hamesc1275e72018-09-26 04:18:30 +0000111 void materialize(orc::MaterializationResponsibility R) override {
112 Materialize(std::move(R));
113 }
114
Lang Hamescb5702c32018-10-06 23:02:06 +0000115 void discard(const orc::JITDylib &JD,
116 const orc::SymbolStringPtr &Name) override {
Lang Hamesc1275e72018-09-26 04:18:30 +0000117 if (Discard)
118 Discard(JD, std::move(Name));
119 else
120 llvm_unreachable("Discard not supported");
121 }
122
123private:
124 MaterializeFunction Materialize;
125 DiscardFunction Discard;
126 DestructorFunction Destructor;
127};
128
Lang Hamesd22bade2017-04-04 17:03:49 +0000129// Base class for Orc tests that will execute code.
130class OrcExecutionTest {
131public:
132
133 OrcExecutionTest() {
134
135 // Initialize the native target if it hasn't been done already.
136 OrcNativeTarget::initialize();
Lang Hamesfd6e8dc2015-10-30 03:20:21 +0000137
138 // Try to select a TargetMachine for the host.
139 TM.reset(EngineBuilder().selectTarget());
140
141 if (TM) {
142 // If we found a TargetMachine, check that it's one that Orc supports.
143 const Triple& TT = TM->getTargetTriple();
Lang Hames4f8194e2016-02-10 01:02:33 +0000144
Lang Hamesec978e22018-03-28 14:47:11 +0000145 // Bail out for windows platforms. We do not support these yet.
Lang Hamesda5c6ac2018-03-28 15:58:14 +0000146 if ((TT.getArch() != Triple::x86_64 && TT.getArch() != Triple::x86) ||
147 TT.isOSWindows())
Lang Hamesec978e22018-03-28 14:47:11 +0000148 return;
149
Lang Hamesa95b0df2018-03-28 03:41:45 +0000150 // Target can JIT?
151 SupportsJIT = TM->getTarget().hasJIT();
152 // Use ability to create callback manager to detect whether Orc
153 // has indirection support on this platform. This way the test
154 // and Orc code do not get out of sync.
Lang Hamesbd0cb782018-05-30 01:57:45 +0000155 SupportsIndirection = !!orc::createLocalCompileCallbackManager(TT, ES, 0);
Lang Hamesfd6e8dc2015-10-30 03:20:21 +0000156 }
Lang Hames130a7c42015-10-28 02:40:04 +0000157 };
158
Lang Hamesfd6e8dc2015-10-30 03:20:21 +0000159protected:
Lang Hamesbd0cb782018-05-30 01:57:45 +0000160 orc::ExecutionSession ES;
Mehdi Amini03b42e42016-04-14 21:59:01 +0000161 LLVMContext Context;
Lang Hamesfd6e8dc2015-10-30 03:20:21 +0000162 std::unique_ptr<TargetMachine> TM;
Lang Hamesa95b0df2018-03-28 03:41:45 +0000163 bool SupportsJIT = false;
164 bool SupportsIndirection = false;
Lang Hames130a7c42015-10-28 02:40:04 +0000165};
166
Lang Hames4a51e5d2015-10-27 17:45:48 +0000167class ModuleBuilder {
168public:
169 ModuleBuilder(LLVMContext &Context, StringRef Triple,
170 StringRef Name);
Lang Hamesdc4260d2015-04-20 20:41:45 +0000171
Lang Hames4a51e5d2015-10-27 17:45:48 +0000172 template <typename FuncType>
Lang Hames130a7c42015-10-28 02:40:04 +0000173 Function* createFunctionDecl(StringRef Name) {
Lang Hames4a51e5d2015-10-27 17:45:48 +0000174 return Function::Create(
175 TypeBuilder<FuncType, false>::get(M->getContext()),
Lang Hames130a7c42015-10-28 02:40:04 +0000176 GlobalValue::ExternalLinkage, Name, M.get());
Lang Hames4a51e5d2015-10-27 17:45:48 +0000177 }
Lang Hamesdc4260d2015-04-20 20:41:45 +0000178
Lang Hames4a51e5d2015-10-27 17:45:48 +0000179 Module* getModule() { return M.get(); }
180 const Module* getModule() const { return M.get(); }
181 std::unique_ptr<Module> takeModule() { return std::move(M); }
Lang Hamesdc4260d2015-04-20 20:41:45 +0000182
Lang Hames4a51e5d2015-10-27 17:45:48 +0000183private:
184 std::unique_ptr<Module> M;
Lang Hames4a51e5d2015-10-27 17:45:48 +0000185};
Lang Hamesdc4260d2015-04-20 20:41:45 +0000186
Lang Hames4a51e5d2015-10-27 17:45:48 +0000187// Dummy struct type.
188struct DummyStruct {
189 int X[256];
190};
Lang Hamesdc4260d2015-04-20 20:41:45 +0000191
Lang Hames4a51e5d2015-10-27 17:45:48 +0000192// TypeBuilder specialization for DummyStruct.
193template <bool XCompile>
194class TypeBuilder<DummyStruct, XCompile> {
195public:
196 static StructType *get(LLVMContext &Context) {
197 return StructType::get(
Serge Gueltone38003f2017-05-09 19:31:13 +0000198 TypeBuilder<types::i<32>[256], XCompile>::get(Context));
Lang Hames4a51e5d2015-10-27 17:45:48 +0000199 }
200};
Lang Hamesdc4260d2015-04-20 20:41:45 +0000201
Lang Hamescf771ad2017-09-28 02:17:35 +0000202template <typename HandleT, typename ModuleT>
Lang Hamesc0056562015-10-20 04:35:02 +0000203class MockBaseLayer {
204public:
205
Lang Hamescf771ad2017-09-28 02:17:35 +0000206 using ModuleHandleT = HandleT;
Lang Hamesc0056562015-10-20 04:35:02 +0000207
Lang Hamescf771ad2017-09-28 02:17:35 +0000208 using AddModuleSignature =
209 Expected<ModuleHandleT>(ModuleT M,
210 std::shared_ptr<JITSymbolResolver> R);
Lang Hamesc0056562015-10-20 04:35:02 +0000211
Lang Hamescf771ad2017-09-28 02:17:35 +0000212 using RemoveModuleSignature = Error(ModuleHandleT H);
213 using FindSymbolSignature = JITSymbol(const std::string &Name,
214 bool ExportedSymbolsOnly);
215 using FindSymbolInSignature = JITSymbol(ModuleHandleT H,
216 const std::string &Name,
217 bool ExportedSymbolsONly);
218 using EmitAndFinalizeSignature = Error(ModuleHandleT H);
219
220 std::function<AddModuleSignature> addModuleImpl;
221 std::function<RemoveModuleSignature> removeModuleImpl;
222 std::function<FindSymbolSignature> findSymbolImpl;
223 std::function<FindSymbolInSignature> findSymbolInImpl;
224 std::function<EmitAndFinalizeSignature> emitAndFinalizeImpl;
225
226 Expected<ModuleHandleT> addModule(ModuleT M,
227 std::shared_ptr<JITSymbolResolver> R) {
228 assert(addModuleImpl &&
229 "addModule called, but no mock implementation was provided");
230 return addModuleImpl(std::move(M), std::move(R));
Lang Hamesc0056562015-10-20 04:35:02 +0000231 }
232
Lang Hames4ce98662017-07-07 02:59:13 +0000233 Error removeModule(ModuleHandleT H) {
Lang Hamescf771ad2017-09-28 02:17:35 +0000234 assert(removeModuleImpl &&
235 "removeModule called, but no mock implementation was provided");
236 return removeModuleImpl(H);
Lang Hamesc0056562015-10-20 04:35:02 +0000237 }
238
Lang Hamesad4a9112016-08-01 20:49:11 +0000239 JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
Lang Hamescf771ad2017-09-28 02:17:35 +0000240 assert(findSymbolImpl &&
241 "findSymbol called, but no mock implementation was provided");
242 return findSymbolImpl(Name, ExportedSymbolsOnly);
Lang Hamesc0056562015-10-20 04:35:02 +0000243 }
244
Lang Hamescd9d49b2017-06-23 23:25:28 +0000245 JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name,
Lang Hamesc0056562015-10-20 04:35:02 +0000246 bool ExportedSymbolsOnly) {
Lang Hamescf771ad2017-09-28 02:17:35 +0000247 assert(findSymbolInImpl &&
248 "findSymbolIn called, but no mock implementation was provided");
249 return findSymbolInImpl(H, Name, ExportedSymbolsOnly);
Lang Hamesc0056562015-10-20 04:35:02 +0000250 }
251
Lang Hamescf771ad2017-09-28 02:17:35 +0000252 Error emitAndFinaliez(ModuleHandleT H) {
253 assert(emitAndFinalizeImpl &&
254 "emitAndFinalize called, but no mock implementation was provided");
255 return emitAndFinalizeImpl(H);
256 }
Lang Hamesc0056562015-10-20 04:35:02 +0000257};
258
Lang Hames4ce98662017-07-07 02:59:13 +0000259class ReturnNullJITSymbol {
260public:
261 template <typename... Args>
262 JITSymbol operator()(Args...) const {
263 return nullptr;
264 }
265};
266
Lang Hamesc0056562015-10-20 04:35:02 +0000267template <typename ReturnT>
268class DoNothingAndReturn {
269public:
Lang Hames4ce98662017-07-07 02:59:13 +0000270 DoNothingAndReturn(ReturnT Ret) : Ret(std::move(Ret)) {}
Lang Hamesc0056562015-10-20 04:35:02 +0000271
272 template <typename... Args>
Lang Hames4ce98662017-07-07 02:59:13 +0000273 void operator()(Args...) const { return Ret; }
Lang Hamesc0056562015-10-20 04:35:02 +0000274private:
Lang Hames4ce98662017-07-07 02:59:13 +0000275 ReturnT Ret;
Lang Hamesc0056562015-10-20 04:35:02 +0000276};
277
278template <>
279class DoNothingAndReturn<void> {
280public:
281 template <typename... Args>
282 void operator()(Args...) const { }
283};
Lang Hamesdc4260d2015-04-20 20:41:45 +0000284
285} // namespace llvm
286
287#endif