[llvm] [cmake] Add possibility to use ChooseMSVCCRT.cmake when include LLVM library
[llvm-core.git] / unittests / ExecutionEngine / Orc / OrcTestCommon.h
blobd82012b5a8531e02c8c51bdad274d569a00715a2
1 //===------ OrcTestCommon.h - Utilities for Orc Unit Tests ------*- C++ -*-===//
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 //===----------------------------------------------------------------------===//
8 //
9 // Common utilities for the Orc unit tests.
11 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_UNITTESTS_EXECUTIONENGINE_ORC_ORCTESTCOMMON_H
15 #define LLVM_UNITTESTS_EXECUTIONENGINE_ORC_ORCTESTCOMMON_H
17 #include "llvm/ExecutionEngine/ExecutionEngine.h"
18 #include "llvm/ExecutionEngine/JITSymbol.h"
19 #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
20 #include "llvm/IR/Function.h"
21 #include "llvm/IR/IRBuilder.h"
22 #include "llvm/IR/LLVMContext.h"
23 #include "llvm/IR/Module.h"
24 #include "llvm/Object/ObjectFile.h"
25 #include "llvm/Support/TargetRegistry.h"
26 #include "llvm/Support/TargetSelect.h"
27 #include "gtest/gtest.h"
29 #include <memory>
31 namespace llvm {
33 namespace orc {
34 // CoreAPIsStandardTest that saves a bunch of boilerplate by providing the
35 // following:
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.
45 // (5) V -- A JITDylib associated with ES.
46 class CoreAPIsBasedStandardTest : public testing::Test {
47 protected:
48 std::shared_ptr<SymbolStringPool> SSP = std::make_shared<SymbolStringPool>();
49 ExecutionSession ES{SSP};
50 JITDylib &JD = ES.createJITDylib("JD");
51 SymbolStringPtr Foo = ES.intern("foo");
52 SymbolStringPtr Bar = ES.intern("bar");
53 SymbolStringPtr Baz = ES.intern("baz");
54 SymbolStringPtr Qux = ES.intern("qux");
55 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);
69 } // end namespace orc
71 class OrcNativeTarget {
72 public:
73 static void initialize() {
74 if (!NativeTargetInitialized) {
75 InitializeNativeTarget();
76 InitializeNativeTargetAsmParser();
77 InitializeNativeTargetAsmPrinter();
78 NativeTargetInitialized = true;
82 private:
83 static bool NativeTargetInitialized;
86 class SimpleMaterializationUnit : public orc::MaterializationUnit {
87 public:
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()>;
94 SimpleMaterializationUnit(
95 orc::SymbolFlagsMap SymbolFlags, MaterializeFunction Materialize,
96 DiscardFunction Discard = DiscardFunction(),
97 DestructorFunction Destructor = DestructorFunction())
98 : MaterializationUnit(std::move(SymbolFlags), orc::VModuleKey()),
99 Materialize(std::move(Materialize)), Discard(std::move(Discard)),
100 Destructor(std::move(Destructor)) {}
102 ~SimpleMaterializationUnit() override {
103 if (Destructor)
104 Destructor();
107 StringRef getName() const override { return "<Simple>"; }
109 void materialize(orc::MaterializationResponsibility R) override {
110 Materialize(std::move(R));
113 void discard(const orc::JITDylib &JD,
114 const orc::SymbolStringPtr &Name) override {
115 if (Discard)
116 Discard(JD, std::move(Name));
117 else
118 llvm_unreachable("Discard not supported");
121 private:
122 MaterializeFunction Materialize;
123 DiscardFunction Discard;
124 DestructorFunction Destructor;
127 // Base class for Orc tests that will execute code.
128 class OrcExecutionTest {
129 public:
131 OrcExecutionTest() {
133 // Initialize the native target if it hasn't been done already.
134 OrcNativeTarget::initialize();
136 // Try to select a TargetMachine for the host.
137 TM.reset(EngineBuilder().selectTarget());
139 if (TM) {
140 // If we found a TargetMachine, check that it's one that Orc supports.
141 const Triple& TT = TM->getTargetTriple();
143 // Bail out for windows platforms. We do not support these yet.
144 if ((TT.getArch() != Triple::x86_64 && TT.getArch() != Triple::x86) ||
145 TT.isOSWindows())
146 return;
148 // 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.
153 SupportsIndirection = !!orc::createLocalCompileCallbackManager(TT, ES, 0);
157 protected:
158 orc::ExecutionSession ES;
159 LLVMContext Context;
160 std::unique_ptr<TargetMachine> TM;
161 bool SupportsJIT = false;
162 bool SupportsIndirection = false;
165 class ModuleBuilder {
166 public:
167 ModuleBuilder(LLVMContext &Context, StringRef Triple,
168 StringRef Name);
170 Function *createFunctionDecl(FunctionType *FTy, StringRef Name) {
171 return Function::Create(FTy, GlobalValue::ExternalLinkage, Name, M.get());
174 Module* getModule() { return M.get(); }
175 const Module* getModule() const { return M.get(); }
176 std::unique_ptr<Module> takeModule() { return std::move(M); }
178 private:
179 std::unique_ptr<Module> M;
182 // Dummy struct type.
183 struct DummyStruct {
184 int X[256];
187 inline StructType *getDummyStructTy(LLVMContext &Context) {
188 return StructType::get(ArrayType::get(Type::getInt32Ty(Context), 256));
191 template <typename HandleT, typename ModuleT>
192 class MockBaseLayer {
193 public:
195 using ModuleHandleT = HandleT;
197 using AddModuleSignature =
198 Expected<ModuleHandleT>(ModuleT M,
199 std::shared_ptr<JITSymbolResolver> R);
201 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);
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;
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));
222 Error removeModule(ModuleHandleT H) {
223 assert(removeModuleImpl &&
224 "removeModule called, but no mock implementation was provided");
225 return removeModuleImpl(H);
228 JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
229 assert(findSymbolImpl &&
230 "findSymbol called, but no mock implementation was provided");
231 return findSymbolImpl(Name, ExportedSymbolsOnly);
234 JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name,
235 bool ExportedSymbolsOnly) {
236 assert(findSymbolInImpl &&
237 "findSymbolIn called, but no mock implementation was provided");
238 return findSymbolInImpl(H, Name, ExportedSymbolsOnly);
241 Error emitAndFinaliez(ModuleHandleT H) {
242 assert(emitAndFinalizeImpl &&
243 "emitAndFinalize called, but no mock implementation was provided");
244 return emitAndFinalizeImpl(H);
248 class ReturnNullJITSymbol {
249 public:
250 template <typename... Args>
251 JITSymbol operator()(Args...) const {
252 return nullptr;
256 template <typename ReturnT>
257 class DoNothingAndReturn {
258 public:
259 DoNothingAndReturn(ReturnT Ret) : Ret(std::move(Ret)) {}
261 template <typename... Args>
262 void operator()(Args...) const { return Ret; }
263 private:
264 ReturnT Ret;
267 template <>
268 class DoNothingAndReturn<void> {
269 public:
270 template <typename... Args>
271 void operator()(Args...) const { }
274 } // namespace llvm
276 #endif