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. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | |
14 | #ifndef LLVM_UNITTESTS_EXECUTIONENGINE_ORC_ORCTESTCOMMON_H |
15 | #define LLVM_UNITTESTS_EXECUTIONENGINE_ORC_ORCTESTCOMMON_H |
16 | |
17 | #include "llvm/ExecutionEngine/JITSymbol.h" |
18 | #include "llvm/ExecutionEngine/Orc/Core.h" |
19 | #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" |
20 | #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" |
21 | #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/MC/TargetRegistry.h" |
26 | #include "llvm/Object/ObjectFile.h" |
27 | #include "llvm/Support/TargetSelect.h" |
28 | #include "gtest/gtest.h" |
29 | |
30 | #include <memory> |
31 | |
32 | namespace llvm { |
33 | |
34 | namespace 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. |
46 | // (5) V -- A JITDylib associated with ES. |
47 | class CoreAPIsBasedStandardTest : public testing::Test { |
48 | public: |
49 | ~CoreAPIsBasedStandardTest() { |
50 | if (auto Err = ES.endSession()) |
51 | ES.reportError(Err: std::move(Err)); |
52 | } |
53 | |
54 | protected: |
55 | class OverridableDispatcher : public InPlaceTaskDispatcher { |
56 | public: |
57 | OverridableDispatcher(CoreAPIsBasedStandardTest &Parent) : Parent(Parent) {} |
58 | void dispatch(std::unique_ptr<Task> T) override; |
59 | |
60 | private: |
61 | CoreAPIsBasedStandardTest &Parent; |
62 | }; |
63 | |
64 | std::unique_ptr<llvm::orc::ExecutorProcessControl> |
65 | makeEPC(std::shared_ptr<SymbolStringPool> SSP); |
66 | |
67 | std::shared_ptr<SymbolStringPool> SSP = std::make_shared<SymbolStringPool>(); |
68 | ExecutionSession ES{makeEPC(SSP)}; |
69 | JITDylib &JD = ES.createBareJITDylib(Name: "JD" ); |
70 | SymbolStringPtr Foo = ES.intern(SymName: "foo" ); |
71 | SymbolStringPtr Bar = ES.intern(SymName: "bar" ); |
72 | SymbolStringPtr Baz = ES.intern(SymName: "baz" ); |
73 | SymbolStringPtr Qux = ES.intern(SymName: "qux" ); |
74 | static constexpr ExecutorAddr FooAddr{1}; |
75 | static constexpr ExecutorAddr BarAddr{2}; |
76 | static constexpr ExecutorAddr BazAddr{3}; |
77 | static constexpr ExecutorAddr QuxAddr{4}; |
78 | ExecutorSymbolDef FooSym{FooAddr, JITSymbolFlags::Exported}; |
79 | ExecutorSymbolDef BarSym{BarAddr, JITSymbolFlags::Exported}; |
80 | ExecutorSymbolDef BazSym{BazAddr, JITSymbolFlags::Exported}; |
81 | ExecutorSymbolDef QuxSym{QuxAddr, JITSymbolFlags::Exported}; |
82 | unique_function<void(std::unique_ptr<Task>)> DispatchOverride; |
83 | }; |
84 | |
85 | } // end namespace orc |
86 | |
87 | class OrcNativeTarget { |
88 | public: |
89 | static void initialize() { |
90 | if (!NativeTargetInitialized) { |
91 | InitializeNativeTarget(); |
92 | InitializeNativeTargetAsmParser(); |
93 | InitializeNativeTargetAsmPrinter(); |
94 | NativeTargetInitialized = true; |
95 | } |
96 | } |
97 | |
98 | private: |
99 | static bool NativeTargetInitialized; |
100 | }; |
101 | |
102 | class SimpleMaterializationUnit : public orc::MaterializationUnit { |
103 | public: |
104 | using MaterializeFunction = |
105 | std::function<void(std::unique_ptr<orc::MaterializationResponsibility>)>; |
106 | using DiscardFunction = |
107 | std::function<void(const orc::JITDylib &, orc::SymbolStringPtr)>; |
108 | using DestructorFunction = std::function<void()>; |
109 | |
110 | SimpleMaterializationUnit( |
111 | orc::SymbolFlagsMap SymbolFlags, MaterializeFunction Materialize, |
112 | orc::SymbolStringPtr InitSym = nullptr, |
113 | DiscardFunction Discard = DiscardFunction(), |
114 | DestructorFunction Destructor = DestructorFunction()) |
115 | : MaterializationUnit( |
116 | Interface(std::move(SymbolFlags), std::move(InitSym))), |
117 | Materialize(std::move(Materialize)), Discard(std::move(Discard)), |
118 | Destructor(std::move(Destructor)) {} |
119 | |
120 | ~SimpleMaterializationUnit() override { |
121 | if (Destructor) |
122 | Destructor(); |
123 | } |
124 | |
125 | StringRef getName() const override { return "<Simple>" ; } |
126 | |
127 | void |
128 | materialize(std::unique_ptr<orc::MaterializationResponsibility> R) override { |
129 | Materialize(std::move(R)); |
130 | } |
131 | |
132 | void discard(const orc::JITDylib &JD, |
133 | const orc::SymbolStringPtr &Name) override { |
134 | if (Discard) |
135 | Discard(JD, std::move(Name)); |
136 | else |
137 | llvm_unreachable("Discard not supported" ); |
138 | } |
139 | |
140 | private: |
141 | MaterializeFunction Materialize; |
142 | DiscardFunction Discard; |
143 | DestructorFunction Destructor; |
144 | }; |
145 | |
146 | class ModuleBuilder { |
147 | public: |
148 | ModuleBuilder(LLVMContext &Context, StringRef Triple, |
149 | StringRef Name); |
150 | |
151 | Function *createFunctionDecl(FunctionType *FTy, StringRef Name) { |
152 | return Function::Create(Ty: FTy, Linkage: GlobalValue::ExternalLinkage, N: Name, M: M.get()); |
153 | } |
154 | |
155 | Module* getModule() { return M.get(); } |
156 | const Module* getModule() const { return M.get(); } |
157 | std::unique_ptr<Module> takeModule() { return std::move(M); } |
158 | |
159 | private: |
160 | std::unique_ptr<Module> M; |
161 | }; |
162 | |
163 | // Dummy struct type. |
164 | struct DummyStruct { |
165 | int X[256]; |
166 | }; |
167 | |
168 | inline StructType *getDummyStructTy(LLVMContext &Context) { |
169 | return StructType::get(elt1: ArrayType::get(ElementType: Type::getInt32Ty(C&: Context), NumElements: 256)); |
170 | } |
171 | |
172 | } // namespace llvm |
173 | |
174 | #endif |
175 | |