1//===- MCJITTestBase.h - Common base class for MCJIT 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// This class implements common functionality required by the MCJIT unit tests,
11// as well as logic to skip tests on unsupported architectures and operating
12// systems.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTBASE_H
17#define LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTBASE_H
18
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"
29
30namespace llvm {
31
32/// Helper class that can build very simple Modules
33class TrivialModuleBuilder {
34protected:
35  LLVMContext Context;
36  IRBuilder<> Builder;
37  std::string BuilderTriple;
38
39  TrivialModuleBuilder(const std::string &Triple)
40    : Builder(Context), BuilderTriple(Triple) {}
41
42  Module *createEmptyModule(StringRef Name = StringRef()) {
43    Module * M = new Module(Name, Context);
44    M->setTargetTriple(Triple::normalize(BuilderTriple));
45    return M;
46  }
47
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);
53
54    BasicBlock *BB = BasicBlock::Create(Context, Name, Result);
55    Builder.SetInsertPoint(BB);
56
57    return Result;
58  }
59
60  void endFunctionWithRet(Function *Func, Value *RetValue) {
61    Builder.CreateRet(RetValue);
62  }
63
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");
69
70    SmallVector<Value*, 1> CallArgs;
71
72    for (Argument &A : Result->args())
73      CallArgs.push_back(&A);
74
75    Value *ReturnCode = Builder.CreateCall(Callee, CallArgs);
76    Builder.CreateRet(ReturnCode);
77    return Result;
78  }
79
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");
85
86    Value *ReturnVal = ConstantInt::get(Context, APInt(32, returnCode));
87    endFunctionWithRet(Result, ReturnVal);
88
89    return Result;
90  }
91
92  // Inserts a function
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);
97
98    Function::arg_iterator args = Result->arg_begin();
99    Value *Arg1 = &*args;
100    Value *Arg2 = &*++args;
101    Value *AddResult = Builder.CreateAdd(Arg1, Arg2);
102
103    endFunctionWithRet(Result, AddResult);
104
105    return Result;
106  }
107
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);
114    return Result;
115  }
116
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,
122                                        Name, M);
123    return Result;
124  }
125
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,
130                                        Func->getName(), M);
131    return Result;
132  }
133
134  // Inserts a global variable of type int32
135  // FIXME: make this a template function to support any type
136  GlobalVariable *insertGlobalInt32(Module *M,
137                                    StringRef name,
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,
142                                                GlobalTy,
143                                                false,
144                                                GlobalValue::ExternalLinkage,
145                                                IV,
146                                                name);
147    return Global;
148  }
149
150  // Inserts a function
151  //   int32_t recursive_add(int32_t num) {
152  //     if (num == 0) {
153  //       return num;
154  //     } else {
155  //       int32_t recursive_param = num - 1;
156  //       return num + Helper(recursive_param);
157  //     }
158  //   }
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);
164    if (!Helper)
165      Helper = Result;
166
167    BasicBlock *BaseCase = BasicBlock::Create(Context, "", Result);
168    BasicBlock *RecursiveCase = BasicBlock::Create(Context, "", Result);
169
170    // if (num == 0)
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);
175
176    //   return num;
177    Builder.SetInsertPoint(BaseCase);
178    Builder.CreateRet(Param);
179
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);
188
189    return Result;
190  }
191
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) {
198    // Define FB1 in B.
199    B.reset(createEmptyModule("B"));
200    FB1 = insertAccumulateFunction(B.get(), nullptr, "FB1");
201
202    // Declare FB1 in A (as an external).
203    A.reset(createEmptyModule("A"));
204    Function *FB1Extern = insertExternalReferenceToFunction(A.get(), FB1);
205
206    // Define FA in A (with a call to FB1).
207    FA = insertAccumulateFunction(A.get(), FB1Extern, "FA");
208
209    // Declare FA in B (as an external)
210    Function *FAExtern = insertExternalReferenceToFunction(B.get(), FA);
211
212    // Define FB2 in B (with a call to FA)
213    FB2 = insertAccumulateFunction(B.get(), FAExtern, "FB2");
214  }
215
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 },
219  void
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());
225
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);
229
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);
233  }
234
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());
242
243    B.reset(createEmptyModule("B"));
244    FB = insertAddFunction(B.get());
245  }
246
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());
253
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(),
257                                                             FAExtern_in_B);
258  }
259
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());
268
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);
272
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);
276  }
277};
278
279class MCJITTestBase : public MCJITTestAPICommon, public TrivialModuleBuilder {
280protected:
281
282  MCJITTestBase()
283    : TrivialModuleBuilder(HostTriple)
284    , OptLevel(CodeGenOpt::None)
285    , RelocModel(Reloc::Default)
286    , CodeModel(CodeModel::Default)
287    , MArch("")
288    , MM(new SectionMemoryManager)
289  {
290    // The architectures below are known to be compatible with MCJIT as they
291    // are copied from test/ExecutionEngine/MCJIT/lit.local.cfg and should be
292    // kept in sync.
293    SupportedArchs.push_back(Triple::aarch64);
294    SupportedArchs.push_back(Triple::arm);
295    SupportedArchs.push_back(Triple::mips);
296    SupportedArchs.push_back(Triple::mipsel);
297    SupportedArchs.push_back(Triple::mips64);
298    SupportedArchs.push_back(Triple::mips64el);
299    SupportedArchs.push_back(Triple::x86);
300    SupportedArchs.push_back(Triple::x86_64);
301
302    // Some architectures have sub-architectures in which tests will fail, like
303    // ARM. These two vectors will define if they do have sub-archs (to avoid
304    // extra work for those who don't), and if so, if they are listed to work
305    HasSubArchs.push_back(Triple::arm);
306    SupportedSubArchs.push_back("armv6");
307    SupportedSubArchs.push_back("armv7");
308
309    UnsupportedEnvironments.push_back(Triple::Cygnus);
310  }
311
312  void createJIT(std::unique_ptr<Module> M) {
313
314    // Due to the EngineBuilder constructor, it is required to have a Module
315    // in order to construct an ExecutionEngine (i.e. MCJIT)
316    assert(M != 0 && "a non-null Module must be provided to create MCJIT");
317
318    EngineBuilder EB(std::move(M));
319    std::string Error;
320    TheJIT.reset(EB.setEngineKind(EngineKind::JIT)
321                 .setMCJITMemoryManager(std::move(MM))
322                 .setErrorStr(&Error)
323                 .setOptLevel(CodeGenOpt::None)
324                 .setCodeModel(CodeModel::JITDefault)
325                 .setRelocationModel(Reloc::Default)
326                 .setMArch(MArch)
327                 .setMCPU(sys::getHostCPUName())
328                 //.setMAttrs(MAttrs)
329                 .create());
330    // At this point, we cannot modify the module any more.
331    assert(TheJIT.get() != NULL && "error creating MCJIT with EngineBuilder");
332  }
333
334  CodeGenOpt::Level OptLevel;
335  Reloc::Model RelocModel;
336  CodeModel::Model CodeModel;
337  StringRef MArch;
338  SmallVector<std::string, 1> MAttrs;
339  std::unique_ptr<ExecutionEngine> TheJIT;
340  std::unique_ptr<RTDyldMemoryManager> MM;
341
342  std::unique_ptr<Module> M;
343};
344
345} // namespace llvm
346
347#endif // LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTBASE_H
348