blob: d82012b5a8531e02c8c51bdad274d569a00715a2 [file] [log] [blame]
Lang Hamesdc4260d2015-04-20 20:41:45 +00001//===------ OrcTestCommon.h - Utilities for Orc Unit Tests ------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Lang Hamesdc4260d2015-04-20 20:41:45 +00006//
7//===----------------------------------------------------------------------===//
8//
9// Common utilities for the Orc unit tests.
10//
11//===----------------------------------------------------------------------===//
12
13
14#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_ORC_ORCTESTCOMMON_H
15#define LLVM_UNITTESTS_EXECUTIONENGINE_ORC_ORCTESTCOMMON_H
16
Chandler Carruth9a67b072017-06-06 11:06:56 +000017#include "llvm/ExecutionEngine/ExecutionEngine.h"
18#include "llvm/ExecutionEngine/JITSymbol.h"
Lang Hamesa95b0df2018-03-28 03:41:45 +000019#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
Lang Hamesdc4260d2015-04-20 20:41:45 +000020#include "llvm/IR/Function.h"
21#include "llvm/IR/IRBuilder.h"
22#include "llvm/IR/LLVMContext.h"
23#include "llvm/IR/Module.h"
Lang Hames859d73c2016-01-09 19:50:40 +000024#include "llvm/Object/ObjectFile.h"
Lang Hamesa95b0df2018-03-28 03:41:45 +000025#include "llvm/Support/TargetRegistry.h"
Lang Hamesfd0c1e712018-07-20 18:31:50 +000026#include "llvm/Support/TargetSelect.h"
27#include "gtest/gtest.h"
28
Lang Hamesdc4260d2015-04-20 20:41:45 +000029#include <memory>
30
31namespace llvm {
32
Lang Hamesfd0c1e712018-07-20 18:31:50 +000033namespace orc {
34// CoreAPIsStandardTest that saves a bunch of boilerplate by providing the
35// following:
36//
37// (1) ES -- An ExecutionSession
38// (2) Foo, Bar, Baz, Qux -- SymbolStringPtrs for strings "foo", "bar", "baz",
39// and "qux" respectively.
40// (3) FooAddr, BarAddr, BazAddr, QuxAddr -- Dummy addresses. Guaranteed
41// distinct and non-null.
42// (4) FooSym, BarSym, BazSym, QuxSym -- JITEvaluatedSymbols with FooAddr,
43// BarAddr, BazAddr, and QuxAddr respectively. All with default strong,
44// linkage and non-hidden visibility.
Lang Hamesd5f56c52018-08-17 21:18:18 +000045// (5) V -- A JITDylib associated with ES.
Lang Hamesfd0c1e712018-07-20 18:31:50 +000046class CoreAPIsBasedStandardTest : public testing::Test {
Lang Hamesfd0c1e712018-07-20 18:31:50 +000047protected:
Lang Hames13014d32018-09-12 21:48:59 +000048 std::shared_ptr<SymbolStringPool> SSP = std::make_shared<SymbolStringPool>();
49 ExecutionSession ES{SSP};
Lang Hamesd5f56c52018-08-17 21:18:18 +000050 JITDylib &JD = ES.createJITDylib("JD");
Lang Hames71d781c2018-09-30 23:18:24 +000051 SymbolStringPtr Foo = ES.intern("foo");
52 SymbolStringPtr Bar = ES.intern("bar");
53 SymbolStringPtr Baz = ES.intern("baz");
54 SymbolStringPtr Qux = ES.intern("qux");
Lang Hamesfd0c1e712018-07-20 18:31:50 +000055 static const JITTargetAddress FooAddr = 1U;
56 static const JITTargetAddress BarAddr = 2U;
57 static const JITTargetAddress BazAddr = 3U;
58 static const JITTargetAddress QuxAddr = 4U;
59 JITEvaluatedSymbol FooSym =
60 JITEvaluatedSymbol(FooAddr, JITSymbolFlags::Exported);
61 JITEvaluatedSymbol BarSym =
62 JITEvaluatedSymbol(BarAddr, JITSymbolFlags::Exported);
63 JITEvaluatedSymbol BazSym =
64 JITEvaluatedSymbol(BazAddr, JITSymbolFlags::Exported);
65 JITEvaluatedSymbol QuxSym =
66 JITEvaluatedSymbol(QuxAddr, JITSymbolFlags::Exported);
67};
68
69} // end namespace orc
70
Lang Hamesd22bade2017-04-04 17:03:49 +000071class OrcNativeTarget {
Lang Hames130a7c42015-10-28 02:40:04 +000072public:
Lang Hamesd22bade2017-04-04 17:03:49 +000073 static void initialize() {
Lang Hames130a7c42015-10-28 02:40:04 +000074 if (!NativeTargetInitialized) {
75 InitializeNativeTarget();
76 InitializeNativeTargetAsmParser();
77 InitializeNativeTargetAsmPrinter();
78 NativeTargetInitialized = true;
79 }
Lang Hamesd22bade2017-04-04 17:03:49 +000080 }
81
82private:
83 static bool NativeTargetInitialized;
84};
85
Lang Hamesc1275e72018-09-26 04:18:30 +000086class SimpleMaterializationUnit : public orc::MaterializationUnit {
87public:
88 using MaterializeFunction =
89 std::function<void(orc::MaterializationResponsibility)>;
90 using DiscardFunction =
91 std::function<void(const orc::JITDylib &, orc::SymbolStringPtr)>;
92 using DestructorFunction = std::function<void()>;
93
94 SimpleMaterializationUnit(
95 orc::SymbolFlagsMap SymbolFlags, MaterializeFunction Materialize,
96 DiscardFunction Discard = DiscardFunction(),
97 DestructorFunction Destructor = DestructorFunction())
Lang Hames8b942742018-10-16 20:13:06 +000098 : MaterializationUnit(std::move(SymbolFlags), orc::VModuleKey()),
Lang Hamesc1275e72018-09-26 04:18:30 +000099 Materialize(std::move(Materialize)), Discard(std::move(Discard)),
100 Destructor(std::move(Destructor)) {}
101
102 ~SimpleMaterializationUnit() override {
103 if (Destructor)
104 Destructor();
105 }
106
Lang Hames53e0df12018-09-28 15:09:14 +0000107 StringRef getName() const override { return "<Simple>"; }
108
Lang Hamesc1275e72018-09-26 04:18:30 +0000109 void materialize(orc::MaterializationResponsibility R) override {
110 Materialize(std::move(R));
111 }
112
Lang Hamescb5702c32018-10-06 23:02:06 +0000113 void discard(const orc::JITDylib &JD,
114 const orc::SymbolStringPtr &Name) override {
Lang Hamesc1275e72018-09-26 04:18:30 +0000115 if (Discard)
116 Discard(JD, std::move(Name));
117 else
118 llvm_unreachable("Discard not supported");
119 }
120
121private:
122 MaterializeFunction Materialize;
123 DiscardFunction Discard;
124 DestructorFunction Destructor;
125};
126
Lang Hamesd22bade2017-04-04 17:03:49 +0000127// Base class for Orc tests that will execute code.
128class OrcExecutionTest {
129public:
130
131 OrcExecutionTest() {
132
133 // Initialize the native target if it hasn't been done already.
134 OrcNativeTarget::initialize();
Lang Hamesfd6e8dc2015-10-30 03:20:21 +0000135
136 // Try to select a TargetMachine for the host.
137 TM.reset(EngineBuilder().selectTarget());
138
139 if (TM) {
140 // If we found a TargetMachine, check that it's one that Orc supports.
141 const Triple& TT = TM->getTargetTriple();
Lang Hames4f8194e2016-02-10 01:02:33 +0000142
Lang Hamesec978e22018-03-28 14:47:11 +0000143 // Bail out for windows platforms. We do not support these yet.
Lang Hamesda5c6ac2018-03-28 15:58:14 +0000144 if ((TT.getArch() != Triple::x86_64 && TT.getArch() != Triple::x86) ||
145 TT.isOSWindows())
Lang Hamesec978e22018-03-28 14:47:11 +0000146 return;
147
Lang Hamesa95b0df2018-03-28 03:41:45 +0000148 // Target can JIT?
149 SupportsJIT = TM->getTarget().hasJIT();
150 // Use ability to create callback manager to detect whether Orc
151 // has indirection support on this platform. This way the test
152 // and Orc code do not get out of sync.
Lang Hamesbd0cb782018-05-30 01:57:45 +0000153 SupportsIndirection = !!orc::createLocalCompileCallbackManager(TT, ES, 0);
Lang Hamesfd6e8dc2015-10-30 03:20:21 +0000154 }
Lang Hames130a7c42015-10-28 02:40:04 +0000155 };
156
Lang Hamesfd6e8dc2015-10-30 03:20:21 +0000157protected:
Lang Hamesbd0cb782018-05-30 01:57:45 +0000158 orc::ExecutionSession ES;
Mehdi Amini03b42e42016-04-14 21:59:01 +0000159 LLVMContext Context;
Lang Hamesfd6e8dc2015-10-30 03:20:21 +0000160 std::unique_ptr<TargetMachine> TM;
Lang Hamesa95b0df2018-03-28 03:41:45 +0000161 bool SupportsJIT = false;
162 bool SupportsIndirection = false;
Lang Hames130a7c42015-10-28 02:40:04 +0000163};
164
Lang Hames4a51e5d2015-10-27 17:45:48 +0000165class ModuleBuilder {
166public:
167 ModuleBuilder(LLVMContext &Context, StringRef Triple,
168 StringRef Name);
Lang Hamesdc4260d2015-04-20 20:41:45 +0000169
James Y Knightc0044112019-01-13 16:09:28 +0000170 Function *createFunctionDecl(FunctionType *FTy, StringRef Name) {
171 return Function::Create(FTy, GlobalValue::ExternalLinkage, Name, M.get());
Lang Hames4a51e5d2015-10-27 17:45:48 +0000172 }
Lang Hamesdc4260d2015-04-20 20:41:45 +0000173
Lang Hames4a51e5d2015-10-27 17:45:48 +0000174 Module* getModule() { return M.get(); }
175 const Module* getModule() const { return M.get(); }
176 std::unique_ptr<Module> takeModule() { return std::move(M); }
Lang Hamesdc4260d2015-04-20 20:41:45 +0000177
Lang Hames4a51e5d2015-10-27 17:45:48 +0000178private:
179 std::unique_ptr<Module> M;
Lang Hames4a51e5d2015-10-27 17:45:48 +0000180};
Lang Hamesdc4260d2015-04-20 20:41:45 +0000181
Lang Hames4a51e5d2015-10-27 17:45:48 +0000182// Dummy struct type.
183struct DummyStruct {
184 int X[256];
185};
Lang Hamesdc4260d2015-04-20 20:41:45 +0000186
James Y Knightc0044112019-01-13 16:09:28 +0000187inline StructType *getDummyStructTy(LLVMContext &Context) {
188 return StructType::get(ArrayType::get(Type::getInt32Ty(Context), 256));
189}
Lang Hamesdc4260d2015-04-20 20:41:45 +0000190
Lang Hamescf771ad2017-09-28 02:17:35 +0000191template <typename HandleT, typename ModuleT>
Lang Hamesc0056562015-10-20 04:35:02 +0000192class MockBaseLayer {
193public:
194
Lang Hamescf771ad2017-09-28 02:17:35 +0000195 using ModuleHandleT = HandleT;
Lang Hamesc0056562015-10-20 04:35:02 +0000196
Lang Hamescf771ad2017-09-28 02:17:35 +0000197 using AddModuleSignature =
198 Expected<ModuleHandleT>(ModuleT M,
199 std::shared_ptr<JITSymbolResolver> R);
Lang Hamesc0056562015-10-20 04:35:02 +0000200
Lang Hamescf771ad2017-09-28 02:17:35 +0000201 using RemoveModuleSignature = Error(ModuleHandleT H);
202 using FindSymbolSignature = JITSymbol(const std::string &Name,
203 bool ExportedSymbolsOnly);
204 using FindSymbolInSignature = JITSymbol(ModuleHandleT H,
205 const std::string &Name,
206 bool ExportedSymbolsONly);
207 using EmitAndFinalizeSignature = Error(ModuleHandleT H);
208
209 std::function<AddModuleSignature> addModuleImpl;
210 std::function<RemoveModuleSignature> removeModuleImpl;
211 std::function<FindSymbolSignature> findSymbolImpl;
212 std::function<FindSymbolInSignature> findSymbolInImpl;
213 std::function<EmitAndFinalizeSignature> emitAndFinalizeImpl;
214
215 Expected<ModuleHandleT> addModule(ModuleT M,
216 std::shared_ptr<JITSymbolResolver> R) {
217 assert(addModuleImpl &&
218 "addModule called, but no mock implementation was provided");
219 return addModuleImpl(std::move(M), std::move(R));
Lang Hamesc0056562015-10-20 04:35:02 +0000220 }
221
Lang Hames4ce98662017-07-07 02:59:13 +0000222 Error removeModule(ModuleHandleT H) {
Lang Hamescf771ad2017-09-28 02:17:35 +0000223 assert(removeModuleImpl &&
224 "removeModule called, but no mock implementation was provided");
225 return removeModuleImpl(H);
Lang Hamesc0056562015-10-20 04:35:02 +0000226 }
227
Lang Hamesad4a9112016-08-01 20:49:11 +0000228 JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
Lang Hamescf771ad2017-09-28 02:17:35 +0000229 assert(findSymbolImpl &&
230 "findSymbol called, but no mock implementation was provided");
231 return findSymbolImpl(Name, ExportedSymbolsOnly);
Lang Hamesc0056562015-10-20 04:35:02 +0000232 }
233
Lang Hamescd9d49b2017-06-23 23:25:28 +0000234 JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name,
Lang Hamesc0056562015-10-20 04:35:02 +0000235 bool ExportedSymbolsOnly) {
Lang Hamescf771ad2017-09-28 02:17:35 +0000236 assert(findSymbolInImpl &&
237 "findSymbolIn called, but no mock implementation was provided");
238 return findSymbolInImpl(H, Name, ExportedSymbolsOnly);
Lang Hamesc0056562015-10-20 04:35:02 +0000239 }
240
Lang Hamescf771ad2017-09-28 02:17:35 +0000241 Error emitAndFinaliez(ModuleHandleT H) {
242 assert(emitAndFinalizeImpl &&
243 "emitAndFinalize called, but no mock implementation was provided");
244 return emitAndFinalizeImpl(H);
245 }
Lang Hamesc0056562015-10-20 04:35:02 +0000246};
247
Lang Hames4ce98662017-07-07 02:59:13 +0000248class ReturnNullJITSymbol {
249public:
250 template <typename... Args>
251 JITSymbol operator()(Args...) const {
252 return nullptr;
253 }
254};
255
Lang Hamesc0056562015-10-20 04:35:02 +0000256template <typename ReturnT>
257class DoNothingAndReturn {
258public:
Lang Hames4ce98662017-07-07 02:59:13 +0000259 DoNothingAndReturn(ReturnT Ret) : Ret(std::move(Ret)) {}
Lang Hamesc0056562015-10-20 04:35:02 +0000260
261 template <typename... Args>
Lang Hames4ce98662017-07-07 02:59:13 +0000262 void operator()(Args...) const { return Ret; }
Lang Hamesc0056562015-10-20 04:35:02 +0000263private:
Lang Hames4ce98662017-07-07 02:59:13 +0000264 ReturnT Ret;
Lang Hamesc0056562015-10-20 04:35:02 +0000265};
266
267template <>
268class DoNothingAndReturn<void> {
269public:
270 template <typename... Args>
271 void operator()(Args...) const { }
272};
Lang Hamesdc4260d2015-04-20 20:41:45 +0000273
274} // namespace llvm
275
276#endif