1 //===- MCJITTestBase.h - Common base class for MCJIT Unit tests -*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This class implements common functionality required by the MCJIT unit tests,
11 // as well as logic to skip tests on unsupported architectures and operating
14 //===----------------------------------------------------------------------===//
16 #ifndef LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTBASE_H
17 #define LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTBASE_H
19 #include "MCJITTestAPICommon.h"
20 #include "llvm/Config/config.h"
21 #include "llvm/ExecutionEngine/ExecutionEngine.h"
22 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
23 #include "llvm/IR/Function.h"
24 #include "llvm/IR/IRBuilder.h"
25 #include "llvm/IR/LLVMContext.h"
26 #include "llvm/IR/Module.h"
27 #include "llvm/IR/TypeBuilder.h"
28 #include "llvm/Support/CodeGen.h"
32 /// Helper class that can build very simple Modules
33 class TrivialModuleBuilder
{
37 std::string BuilderTriple
;
39 TrivialModuleBuilder(const std::string
&Triple
)
40 : Builder(Context
), BuilderTriple(Triple
) {}
42 Module
*createEmptyModule(StringRef Name
= StringRef()) {
43 Module
* M
= new Module(Name
, Context
);
44 M
->setTargetTriple(Triple::normalize(BuilderTriple
));
48 template<typename FuncType
>
49 Function
*startFunction(Module
*M
, StringRef Name
) {
50 Function
*Result
= Function::Create(
51 TypeBuilder
<FuncType
, false>::get(Context
),
52 GlobalValue::ExternalLinkage
, Name
, M
);
54 BasicBlock
*BB
= BasicBlock::Create(Context
, Name
, Result
);
55 Builder
.SetInsertPoint(BB
);
60 void endFunctionWithRet(Function
*Func
, Value
*RetValue
) {
61 Builder
.CreateRet(RetValue
);
64 // Inserts a simple function that invokes Callee and takes the same arguments:
65 // int Caller(...) { return Callee(...); }
66 template<typename Signature
>
67 Function
*insertSimpleCallFunction(Module
*M
, Function
*Callee
) {
68 Function
*Result
= startFunction
<Signature
>(M
, "caller");
70 SmallVector
<Value
*, 1> CallArgs
;
72 for (Argument
&A
: Result
->args())
73 CallArgs
.push_back(&A
);
75 Value
*ReturnCode
= Builder
.CreateCall(Callee
, CallArgs
);
76 Builder
.CreateRet(ReturnCode
);
80 // Inserts a function named 'main' that returns a uint32_t:
81 // int32_t main() { return X; }
82 // where X is given by returnCode
83 Function
*insertMainFunction(Module
*M
, uint32_t returnCode
) {
84 Function
*Result
= startFunction
<int32_t(void)>(M
, "main");
86 Value
*ReturnVal
= ConstantInt::get(Context
, APInt(32, returnCode
));
87 endFunctionWithRet(Result
, ReturnVal
);
93 // int32_t add(int32_t a, int32_t b) { return a + b; }
94 // in the current module and returns a pointer to it.
95 Function
*insertAddFunction(Module
*M
, StringRef Name
= "add") {
96 Function
*Result
= startFunction
<int32_t(int32_t, int32_t)>(M
, Name
);
98 Function::arg_iterator args
= Result
->arg_begin();
100 Value
*Arg2
= &*++args
;
101 Value
*AddResult
= Builder
.CreateAdd(Arg1
, Arg2
);
103 endFunctionWithRet(Result
, AddResult
);
108 // Inserts a declaration to a function defined elsewhere
109 template <typename FuncType
>
110 Function
*insertExternalReferenceToFunction(Module
*M
, StringRef Name
) {
111 Function
*Result
= Function::Create(
112 TypeBuilder
<FuncType
, false>::get(Context
),
113 GlobalValue::ExternalLinkage
, Name
, M
);
117 // Inserts an declaration to a function defined elsewhere
118 Function
*insertExternalReferenceToFunction(Module
*M
, StringRef Name
,
119 FunctionType
*FuncTy
) {
120 Function
*Result
= Function::Create(FuncTy
,
121 GlobalValue::ExternalLinkage
,
126 // Inserts an declaration to a function defined elsewhere
127 Function
*insertExternalReferenceToFunction(Module
*M
, Function
*Func
) {
128 Function
*Result
= Function::Create(Func
->getFunctionType(),
129 GlobalValue::ExternalLinkage
,
134 // Inserts a global variable of type int32
135 // FIXME: make this a template function to support any type
136 GlobalVariable
*insertGlobalInt32(Module
*M
,
138 int32_t InitialValue
) {
139 Type
*GlobalTy
= TypeBuilder
<types::i
<32>, true>::get(Context
);
140 Constant
*IV
= ConstantInt::get(Context
, APInt(32, InitialValue
));
141 GlobalVariable
*Global
= new GlobalVariable(*M
,
144 GlobalValue::ExternalLinkage
,
150 // Inserts a function
151 // int32_t recursive_add(int32_t num) {
155 // int32_t recursive_param = num - 1;
156 // return num + Helper(recursive_param);
159 // NOTE: if Helper is left as the default parameter, Helper == recursive_add.
160 Function
*insertAccumulateFunction(Module
*M
,
161 Function
*Helper
= nullptr,
162 StringRef Name
= "accumulate") {
163 Function
*Result
= startFunction
<int32_t(int32_t)>(M
, Name
);
167 BasicBlock
*BaseCase
= BasicBlock::Create(Context
, "", Result
);
168 BasicBlock
*RecursiveCase
= BasicBlock::Create(Context
, "", Result
);
171 Value
*Param
= &*Result
->arg_begin();
172 Value
*Zero
= ConstantInt::get(Context
, APInt(32, 0));
173 Builder
.CreateCondBr(Builder
.CreateICmpEQ(Param
, Zero
),
174 BaseCase
, RecursiveCase
);
177 Builder
.SetInsertPoint(BaseCase
);
178 Builder
.CreateRet(Param
);
180 // int32_t recursive_param = num - 1;
181 // return Helper(recursive_param);
182 Builder
.SetInsertPoint(RecursiveCase
);
183 Value
*One
= ConstantInt::get(Context
, APInt(32, 1));
184 Value
*RecursiveParam
= Builder
.CreateSub(Param
, One
);
185 Value
*RecursiveReturn
= Builder
.CreateCall(Helper
, RecursiveParam
);
186 Value
*Accumulator
= Builder
.CreateAdd(Param
, RecursiveReturn
);
187 Builder
.CreateRet(Accumulator
);
192 // Populates Modules A and B:
193 // Module A { Extern FB1, Function FA which calls FB1 },
194 // Module B { Extern FA, Function FB1, Function FB2 which calls FA },
195 void createCrossModuleRecursiveCase(std::unique_ptr
<Module
> &A
, Function
*&FA
,
196 std::unique_ptr
<Module
> &B
,
197 Function
*&FB1
, Function
*&FB2
) {
199 B
.reset(createEmptyModule("B"));
200 FB1
= insertAccumulateFunction(B
.get(), nullptr, "FB1");
202 // Declare FB1 in A (as an external).
203 A
.reset(createEmptyModule("A"));
204 Function
*FB1Extern
= insertExternalReferenceToFunction(A
.get(), FB1
);
206 // Define FA in A (with a call to FB1).
207 FA
= insertAccumulateFunction(A
.get(), FB1Extern
, "FA");
209 // Declare FA in B (as an external)
210 Function
*FAExtern
= insertExternalReferenceToFunction(B
.get(), FA
);
212 // Define FB2 in B (with a call to FA)
213 FB2
= insertAccumulateFunction(B
.get(), FAExtern
, "FB2");
216 // Module A { Function FA },
217 // Module B { Extern FA, Function FB which calls FA },
218 // Module C { Extern FB, Function FC which calls FB },
220 createThreeModuleChainedCallsCase(std::unique_ptr
<Module
> &A
, Function
*&FA
,
221 std::unique_ptr
<Module
> &B
, Function
*&FB
,
222 std::unique_ptr
<Module
> &C
, Function
*&FC
) {
223 A
.reset(createEmptyModule("A"));
224 FA
= insertAddFunction(A
.get());
226 B
.reset(createEmptyModule("B"));
227 Function
*FAExtern_in_B
= insertExternalReferenceToFunction(B
.get(), FA
);
228 FB
= insertSimpleCallFunction
<int32_t(int32_t, int32_t)>(B
.get(), FAExtern_in_B
);
230 C
.reset(createEmptyModule("C"));
231 Function
*FBExtern_in_C
= insertExternalReferenceToFunction(C
.get(), FB
);
232 FC
= insertSimpleCallFunction
<int32_t(int32_t, int32_t)>(C
.get(), FBExtern_in_C
);
235 // Module A { Function FA },
236 // Populates Modules A and B:
237 // Module B { Function FB }
238 void createTwoModuleCase(std::unique_ptr
<Module
> &A
, Function
*&FA
,
239 std::unique_ptr
<Module
> &B
, Function
*&FB
) {
240 A
.reset(createEmptyModule("A"));
241 FA
= insertAddFunction(A
.get());
243 B
.reset(createEmptyModule("B"));
244 FB
= insertAddFunction(B
.get());
247 // Module A { Function FA },
248 // Module B { Extern FA, Function FB which calls FA }
249 void createTwoModuleExternCase(std::unique_ptr
<Module
> &A
, Function
*&FA
,
250 std::unique_ptr
<Module
> &B
, Function
*&FB
) {
251 A
.reset(createEmptyModule("A"));
252 FA
= insertAddFunction(A
.get());
254 B
.reset(createEmptyModule("B"));
255 Function
*FAExtern_in_B
= insertExternalReferenceToFunction(B
.get(), FA
);
256 FB
= insertSimpleCallFunction
<int32_t(int32_t, int32_t)>(B
.get(),
260 // Module A { Function FA },
261 // Module B { Extern FA, Function FB which calls FA },
262 // Module C { Extern FB, Function FC which calls FA },
263 void createThreeModuleCase(std::unique_ptr
<Module
> &A
, Function
*&FA
,
264 std::unique_ptr
<Module
> &B
, Function
*&FB
,
265 std::unique_ptr
<Module
> &C
, Function
*&FC
) {
266 A
.reset(createEmptyModule("A"));
267 FA
= insertAddFunction(A
.get());
269 B
.reset(createEmptyModule("B"));
270 Function
*FAExtern_in_B
= insertExternalReferenceToFunction(B
.get(), FA
);
271 FB
= insertSimpleCallFunction
<int32_t(int32_t, int32_t)>(B
.get(), FAExtern_in_B
);
273 C
.reset(createEmptyModule("C"));
274 Function
*FAExtern_in_C
= insertExternalReferenceToFunction(C
.get(), FA
);
275 FC
= insertSimpleCallFunction
<int32_t(int32_t, int32_t)>(C
.get(), FAExtern_in_C
);
279 class MCJITTestBase
: public MCJITTestAPICommon
, public TrivialModuleBuilder
{
282 : TrivialModuleBuilder(HostTriple
), OptLevel(CodeGenOpt::None
),
283 CodeModel(CodeModel::Small
), MArch(""), MM(new SectionMemoryManager
) {
284 // The architectures below are known to be compatible with MCJIT as they
285 // are copied from test/ExecutionEngine/MCJIT/lit.local.cfg and should be
287 SupportedArchs
.push_back(Triple::aarch64
);
288 SupportedArchs
.push_back(Triple::arm
);
289 SupportedArchs
.push_back(Triple::mips
);
290 SupportedArchs
.push_back(Triple::mipsel
);
291 SupportedArchs
.push_back(Triple::mips64
);
292 SupportedArchs
.push_back(Triple::mips64el
);
293 SupportedArchs
.push_back(Triple::x86
);
294 SupportedArchs
.push_back(Triple::x86_64
);
296 // Some architectures have sub-architectures in which tests will fail, like
297 // ARM. These two vectors will define if they do have sub-archs (to avoid
298 // extra work for those who don't), and if so, if they are listed to work
299 HasSubArchs
.push_back(Triple::arm
);
300 SupportedSubArchs
.push_back("armv6");
301 SupportedSubArchs
.push_back("armv7");
303 UnsupportedEnvironments
.push_back(Triple::Cygnus
);
306 void createJIT(std::unique_ptr
<Module
> M
) {
308 // Due to the EngineBuilder constructor, it is required to have a Module
309 // in order to construct an ExecutionEngine (i.e. MCJIT)
310 assert(M
!= 0 && "a non-null Module must be provided to create MCJIT");
312 EngineBuilder
EB(std::move(M
));
314 TheJIT
.reset(EB
.setEngineKind(EngineKind::JIT
)
315 .setMCJITMemoryManager(std::move(MM
))
317 .setOptLevel(CodeGenOpt::None
)
319 .setMCPU(sys::getHostCPUName())
322 // At this point, we cannot modify the module any more.
323 assert(TheJIT
.get() != NULL
&& "error creating MCJIT with EngineBuilder");
326 CodeGenOpt::Level OptLevel
;
327 CodeModel::Model CodeModel
;
329 SmallVector
<std::string
, 1> MAttrs
;
330 std::unique_ptr
<ExecutionEngine
> TheJIT
;
331 std::unique_ptr
<RTDyldMemoryManager
> MM
;
333 std::unique_ptr
<Module
> M
;
338 #endif // LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTBASE_H