blob: e25c513d94709a835af5178e7c79f7957b7f5f4b [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"
Lang Hames859d73c2016-01-09 19:50:40 +000025#include "llvm/Object/ObjectFile.h"
Lang Hamesa95b0df2018-03-28 03:41:45 +000026#include "llvm/Support/TargetRegistry.h"
Lang Hamesfd0c1e712018-07-20 18:31:50 +000027#include "llvm/Support/TargetSelect.h"
28#include "gtest/gtest.h"
29
Lang Hamesdc4260d2015-04-20 20:41:45 +000030#include <memory>
31
32namespace llvm {
33
Lang Hamesfd0c1e712018-07-20 18:31:50 +000034namespace orc {
35// CoreAPIsStandardTest that saves a bunch of boilerplate by providing the
36// following:
37//
38// (1) ES -- An ExecutionSession
39// (2) Foo, Bar, Baz, Qux -- SymbolStringPtrs for strings "foo", "bar", "baz",
40// and "qux" respectively.
41// (3) FooAddr, BarAddr, BazAddr, QuxAddr -- Dummy addresses. Guaranteed
42// distinct and non-null.
43// (4) FooSym, BarSym, BazSym, QuxSym -- JITEvaluatedSymbols with FooAddr,
44// BarAddr, BazAddr, and QuxAddr respectively. All with default strong,
45// linkage and non-hidden visibility.
Lang Hamesd5f56c52018-08-17 21:18:18 +000046// (5) V -- A JITDylib associated with ES.
Lang Hamesfd0c1e712018-07-20 18:31:50 +000047class CoreAPIsBasedStandardTest : public testing::Test {
Lang Hamesfd0c1e712018-07-20 18:31:50 +000048protected:
Lang Hames13014d32018-09-12 21:48:59 +000049 std::shared_ptr<SymbolStringPool> SSP = std::make_shared<SymbolStringPool>();
50 ExecutionSession ES{SSP};
Lang Hamesd5f56c52018-08-17 21:18:18 +000051 JITDylib &JD = ES.createJITDylib("JD");
Lang Hames71d781c2018-09-30 23:18:24 +000052 SymbolStringPtr Foo = ES.intern("foo");
53 SymbolStringPtr Bar = ES.intern("bar");
54 SymbolStringPtr Baz = ES.intern("baz");
55 SymbolStringPtr Qux = ES.intern("qux");
Lang Hamesfd0c1e712018-07-20 18:31:50 +000056 static const JITTargetAddress FooAddr = 1U;
57 static const JITTargetAddress BarAddr = 2U;
58 static const JITTargetAddress BazAddr = 3U;
59 static const JITTargetAddress QuxAddr = 4U;
60 JITEvaluatedSymbol FooSym =
61 JITEvaluatedSymbol(FooAddr, JITSymbolFlags::Exported);
62 JITEvaluatedSymbol BarSym =
63 JITEvaluatedSymbol(BarAddr, JITSymbolFlags::Exported);
64 JITEvaluatedSymbol BazSym =
65 JITEvaluatedSymbol(BazAddr, JITSymbolFlags::Exported);
66 JITEvaluatedSymbol QuxSym =
67 JITEvaluatedSymbol(QuxAddr, JITSymbolFlags::Exported);
68};
69
70} // end namespace orc
71
Lang Hamesd22bade2017-04-04 17:03:49 +000072class OrcNativeTarget {
Lang Hames130a7c42015-10-28 02:40:04 +000073public:
Lang Hamesd22bade2017-04-04 17:03:49 +000074 static void initialize() {
Lang Hames130a7c42015-10-28 02:40:04 +000075 if (!NativeTargetInitialized) {
76 InitializeNativeTarget();
77 InitializeNativeTargetAsmParser();
78 InitializeNativeTargetAsmPrinter();
79 NativeTargetInitialized = true;
80 }
Lang Hamesd22bade2017-04-04 17:03:49 +000081 }
82
83private:
84 static bool NativeTargetInitialized;
85};
86
Lang Hamesc1275e72018-09-26 04:18:30 +000087class SimpleMaterializationUnit : public orc::MaterializationUnit {
88public:
89 using MaterializeFunction =
90 std::function<void(orc::MaterializationResponsibility)>;
91 using DiscardFunction =
92 std::function<void(const orc::JITDylib &, orc::SymbolStringPtr)>;
93 using DestructorFunction = std::function<void()>;
94
95 SimpleMaterializationUnit(
96 orc::SymbolFlagsMap SymbolFlags, MaterializeFunction Materialize,
97 DiscardFunction Discard = DiscardFunction(),
98 DestructorFunction Destructor = DestructorFunction())
Lang Hames8b942742018-10-16 20:13:06 +000099 : MaterializationUnit(std::move(SymbolFlags), orc::VModuleKey()),
Lang Hamesc1275e72018-09-26 04:18:30 +0000100 Materialize(std::move(Materialize)), Discard(std::move(Discard)),
101 Destructor(std::move(Destructor)) {}
102
103 ~SimpleMaterializationUnit() override {
104 if (Destructor)
105 Destructor();
106 }
107
Lang Hames53e0df12018-09-28 15:09:14 +0000108 StringRef getName() const override { return "<Simple>"; }
109
Lang Hamesc1275e72018-09-26 04:18:30 +0000110 void materialize(orc::MaterializationResponsibility R) override {
111 Materialize(std::move(R));
112 }
113
Lang Hamescb5702c32018-10-06 23:02:06 +0000114 void discard(const orc::JITDylib &JD,
115 const orc::SymbolStringPtr &Name) override {
Lang Hamesc1275e72018-09-26 04:18:30 +0000116 if (Discard)
117 Discard(JD, std::move(Name));
118 else
119 llvm_unreachable("Discard not supported");
120 }
121
122private:
123 MaterializeFunction Materialize;
124 DiscardFunction Discard;
125 DestructorFunction Destructor;
126};
127
Lang Hamesd22bade2017-04-04 17:03:49 +0000128// Base class for Orc tests that will execute code.
129class OrcExecutionTest {
130public:
131
132 OrcExecutionTest() {
133
134 // Initialize the native target if it hasn't been done already.
135 OrcNativeTarget::initialize();
Lang Hamesfd6e8dc2015-10-30 03:20:21 +0000136
137 // Try to select a TargetMachine for the host.
138 TM.reset(EngineBuilder().selectTarget());
139
140 if (TM) {
141 // If we found a TargetMachine, check that it's one that Orc supports.
142 const Triple& TT = TM->getTargetTriple();
Lang Hames4f8194e2016-02-10 01:02:33 +0000143
Lang Hamesec978e22018-03-28 14:47:11 +0000144 // Bail out for windows platforms. We do not support these yet.
Lang Hamesda5c6ac2018-03-28 15:58:14 +0000145 if ((TT.getArch() != Triple::x86_64 && TT.getArch() != Triple::x86) ||
146 TT.isOSWindows())
Lang Hamesec978e22018-03-28 14:47:11 +0000147 return;
148
Lang Hamesa95b0df2018-03-28 03:41:45 +0000149 // Target can JIT?
150 SupportsJIT = TM->getTarget().hasJIT();
151 // Use ability to create callback manager to detect whether Orc
152 // has indirection support on this platform. This way the test
153 // and Orc code do not get out of sync.
Lang Hamesbd0cb782018-05-30 01:57:45 +0000154 SupportsIndirection = !!orc::createLocalCompileCallbackManager(TT, ES, 0);
Lang Hamesfd6e8dc2015-10-30 03:20:21 +0000155 }
Lang Hames130a7c42015-10-28 02:40:04 +0000156 };
157
Lang Hamesfd6e8dc2015-10-30 03:20:21 +0000158protected:
Lang Hamesbd0cb782018-05-30 01:57:45 +0000159 orc::ExecutionSession ES;
Mehdi Amini03b42e42016-04-14 21:59:01 +0000160 LLVMContext Context;
Lang Hamesfd6e8dc2015-10-30 03:20:21 +0000161 std::unique_ptr<TargetMachine> TM;
Lang Hamesa95b0df2018-03-28 03:41:45 +0000162 bool SupportsJIT = false;
163 bool SupportsIndirection = false;
Lang Hames130a7c42015-10-28 02:40:04 +0000164};
165
Lang Hames4a51e5d2015-10-27 17:45:48 +0000166class ModuleBuilder {
167public:
168 ModuleBuilder(LLVMContext &Context, StringRef Triple,
169 StringRef Name);
Lang Hamesdc4260d2015-04-20 20:41:45 +0000170
James Y Knightc0044112019-01-13 16:09:28 +0000171 Function *createFunctionDecl(FunctionType *FTy, StringRef Name) {
172 return Function::Create(FTy, GlobalValue::ExternalLinkage, Name, M.get());
Lang Hames4a51e5d2015-10-27 17:45:48 +0000173 }
Lang Hamesdc4260d2015-04-20 20:41:45 +0000174
Lang Hames4a51e5d2015-10-27 17:45:48 +0000175 Module* getModule() { return M.get(); }
176 const Module* getModule() const { return M.get(); }
177 std::unique_ptr<Module> takeModule() { return std::move(M); }
Lang Hamesdc4260d2015-04-20 20:41:45 +0000178
Lang Hames4a51e5d2015-10-27 17:45:48 +0000179private:
180 std::unique_ptr<Module> M;
Lang Hames4a51e5d2015-10-27 17:45:48 +0000181};
Lang Hamesdc4260d2015-04-20 20:41:45 +0000182
Lang Hames4a51e5d2015-10-27 17:45:48 +0000183// Dummy struct type.
184struct DummyStruct {
185 int X[256];
186};
Lang Hamesdc4260d2015-04-20 20:41:45 +0000187
James Y Knightc0044112019-01-13 16:09:28 +0000188inline StructType *getDummyStructTy(LLVMContext &Context) {
189 return StructType::get(ArrayType::get(Type::getInt32Ty(Context), 256));
190}
Lang Hamesdc4260d2015-04-20 20:41:45 +0000191
Lang Hamescf771ad2017-09-28 02:17:35 +0000192template <typename HandleT, typename ModuleT>
Lang Hamesc0056562015-10-20 04:35:02 +0000193class MockBaseLayer {
194public:
195
Lang Hamescf771ad2017-09-28 02:17:35 +0000196 using ModuleHandleT = HandleT;
Lang Hamesc0056562015-10-20 04:35:02 +0000197
Lang Hamescf771ad2017-09-28 02:17:35 +0000198 using AddModuleSignature =
199 Expected<ModuleHandleT>(ModuleT M,
200 std::shared_ptr<JITSymbolResolver> R);
Lang Hamesc0056562015-10-20 04:35:02 +0000201
Lang Hamescf771ad2017-09-28 02:17:35 +0000202 using RemoveModuleSignature = Error(ModuleHandleT H);
203 using FindSymbolSignature = JITSymbol(const std::string &Name,
204 bool ExportedSymbolsOnly);
205 using FindSymbolInSignature = JITSymbol(ModuleHandleT H,
206 const std::string &Name,
207 bool ExportedSymbolsONly);
208 using EmitAndFinalizeSignature = Error(ModuleHandleT H);
209
210 std::function<AddModuleSignature> addModuleImpl;
211 std::function<RemoveModuleSignature> removeModuleImpl;
212 std::function<FindSymbolSignature> findSymbolImpl;
213 std::function<FindSymbolInSignature> findSymbolInImpl;
214 std::function<EmitAndFinalizeSignature> emitAndFinalizeImpl;
215
216 Expected<ModuleHandleT> addModule(ModuleT M,
217 std::shared_ptr<JITSymbolResolver> R) {
218 assert(addModuleImpl &&
219 "addModule called, but no mock implementation was provided");
220 return addModuleImpl(std::move(M), std::move(R));
Lang Hamesc0056562015-10-20 04:35:02 +0000221 }
222
Lang Hames4ce98662017-07-07 02:59:13 +0000223 Error removeModule(ModuleHandleT H) {
Lang Hamescf771ad2017-09-28 02:17:35 +0000224 assert(removeModuleImpl &&
225 "removeModule called, but no mock implementation was provided");
226 return removeModuleImpl(H);
Lang Hamesc0056562015-10-20 04:35:02 +0000227 }
228
Lang Hamesad4a9112016-08-01 20:49:11 +0000229 JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
Lang Hamescf771ad2017-09-28 02:17:35 +0000230 assert(findSymbolImpl &&
231 "findSymbol called, but no mock implementation was provided");
232 return findSymbolImpl(Name, ExportedSymbolsOnly);
Lang Hamesc0056562015-10-20 04:35:02 +0000233 }
234
Lang Hamescd9d49b2017-06-23 23:25:28 +0000235 JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name,
Lang Hamesc0056562015-10-20 04:35:02 +0000236 bool ExportedSymbolsOnly) {
Lang Hamescf771ad2017-09-28 02:17:35 +0000237 assert(findSymbolInImpl &&
238 "findSymbolIn called, but no mock implementation was provided");
239 return findSymbolInImpl(H, Name, ExportedSymbolsOnly);
Lang Hamesc0056562015-10-20 04:35:02 +0000240 }
241
Lang Hamescf771ad2017-09-28 02:17:35 +0000242 Error emitAndFinaliez(ModuleHandleT H) {
243 assert(emitAndFinalizeImpl &&
244 "emitAndFinalize called, but no mock implementation was provided");
245 return emitAndFinalizeImpl(H);
246 }
Lang Hamesc0056562015-10-20 04:35:02 +0000247};
248
Lang Hames4ce98662017-07-07 02:59:13 +0000249class ReturnNullJITSymbol {
250public:
251 template <typename... Args>
252 JITSymbol operator()(Args...) const {
253 return nullptr;
254 }
255};
256
Lang Hamesc0056562015-10-20 04:35:02 +0000257template <typename ReturnT>
258class DoNothingAndReturn {
259public:
Lang Hames4ce98662017-07-07 02:59:13 +0000260 DoNothingAndReturn(ReturnT Ret) : Ret(std::move(Ret)) {}
Lang Hamesc0056562015-10-20 04:35:02 +0000261
262 template <typename... Args>
Lang Hames4ce98662017-07-07 02:59:13 +0000263 void operator()(Args...) const { return Ret; }
Lang Hamesc0056562015-10-20 04:35:02 +0000264private:
Lang Hames4ce98662017-07-07 02:59:13 +0000265 ReturnT Ret;
Lang Hamesc0056562015-10-20 04:35:02 +0000266};
267
268template <>
269class DoNothingAndReturn<void> {
270public:
271 template <typename... Args>
272 void operator()(Args...) const { }
273};
Lang Hamesdc4260d2015-04-20 20:41:45 +0000274
275} // namespace llvm
276
277#endif