| Andrew Kaylor | 5e7d792 | 2012-10-04 20:29:44 +0000 | [diff] [blame] | 1 | //===- MCJITTestBase.h - Common base class for MCJIT Unit tests  ----------===// | 
|  | 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 |  | 
|  | 17 | #ifndef MCJIT_TEST_BASE_H | 
|  | 18 | #define MCJIT_TEST_BASE_H | 
|  | 19 |  | 
| Andrew Kaylor | 5e7d792 | 2012-10-04 20:29:44 +0000 | [diff] [blame] | 20 | #include "llvm/Config/config.h" | 
|  | 21 | #include "llvm/ExecutionEngine/ExecutionEngine.h" | 
| Andrew Kaylor | ab5ba51 | 2012-11-27 19:42:02 +0000 | [diff] [blame] | 22 | #include "llvm/ExecutionEngine/SectionMemoryManager.h" | 
| Chandler Carruth | 9fb823b | 2013-01-02 11:36:10 +0000 | [diff] [blame] | 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" | 
| Andrew Kaylor | 5e7d792 | 2012-10-04 20:29:44 +0000 | [diff] [blame] | 28 | #include "llvm/Support/CodeGen.h" | 
| Andrew Kaylor | 31be5ef | 2013-04-29 17:49:40 +0000 | [diff] [blame] | 29 | #include "MCJITTestAPICommon.h" | 
| Andrew Kaylor | 5e7d792 | 2012-10-04 20:29:44 +0000 | [diff] [blame] | 30 |  | 
|  | 31 | namespace llvm { | 
|  | 32 |  | 
| Daniel Malea | 4146b04 | 2013-06-28 20:37:20 +0000 | [diff] [blame] | 33 | /// Helper class that can build very simple Modules | 
|  | 34 | class TrivialModuleBuilder { | 
| Andrew Kaylor | 5e7d792 | 2012-10-04 20:29:44 +0000 | [diff] [blame] | 35 | protected: | 
| Daniel Malea | 4146b04 | 2013-06-28 20:37:20 +0000 | [diff] [blame] | 36 | LLVMContext Context; | 
|  | 37 | IRBuilder<> Builder; | 
|  | 38 | std::string BuilderTriple; | 
| Andrew Kaylor | 5e7d792 | 2012-10-04 20:29:44 +0000 | [diff] [blame] | 39 |  | 
| Daniel Malea | 4146b04 | 2013-06-28 20:37:20 +0000 | [diff] [blame] | 40 | TrivialModuleBuilder(const std::string &Triple) | 
|  | 41 | : Builder(Context), BuilderTriple(Triple) {} | 
| Andrew Kaylor | 5e7d792 | 2012-10-04 20:29:44 +0000 | [diff] [blame] | 42 |  | 
| Daniel Malea | 4146b04 | 2013-06-28 20:37:20 +0000 | [diff] [blame] | 43 | Module *createEmptyModule(StringRef Name = StringRef()) { | 
| Andrew Kaylor | 5e7d792 | 2012-10-04 20:29:44 +0000 | [diff] [blame] | 44 | Module * M = new Module(Name, Context); | 
| Daniel Malea | 4146b04 | 2013-06-28 20:37:20 +0000 | [diff] [blame] | 45 | M->setTargetTriple(Triple::normalize(BuilderTriple)); | 
| Andrew Kaylor | 5e7d792 | 2012-10-04 20:29:44 +0000 | [diff] [blame] | 46 | return M; | 
|  | 47 | } | 
|  | 48 |  | 
|  | 49 | template<typename FuncType> | 
|  | 50 | Function *startFunction(Module *M, StringRef Name) { | 
|  | 51 | Function *Result = Function::Create( | 
|  | 52 | TypeBuilder<FuncType, false>::get(Context), | 
|  | 53 | GlobalValue::ExternalLinkage, Name, M); | 
|  | 54 |  | 
|  | 55 | BasicBlock *BB = BasicBlock::Create(Context, Name, Result); | 
|  | 56 | Builder.SetInsertPoint(BB); | 
|  | 57 |  | 
|  | 58 | return Result; | 
|  | 59 | } | 
|  | 60 |  | 
|  | 61 | void endFunctionWithRet(Function *Func, Value *RetValue) { | 
|  | 62 | Builder.CreateRet(RetValue); | 
|  | 63 | } | 
|  | 64 |  | 
|  | 65 | // Inserts a simple function that invokes Callee and takes the same arguments: | 
|  | 66 | //    int Caller(...) { return Callee(...); } | 
|  | 67 | template<typename Signature> | 
|  | 68 | Function *insertSimpleCallFunction(Module *M, Function *Callee) { | 
|  | 69 | Function *Result = startFunction<Signature>(M, "caller"); | 
|  | 70 |  | 
|  | 71 | SmallVector<Value*, 1> CallArgs; | 
|  | 72 |  | 
|  | 73 | Function::arg_iterator arg_iter = Result->arg_begin(); | 
|  | 74 | for(;arg_iter != Result->arg_end(); ++arg_iter) | 
|  | 75 | CallArgs.push_back(arg_iter); | 
|  | 76 |  | 
|  | 77 | Value *ReturnCode = Builder.CreateCall(Callee, CallArgs); | 
|  | 78 | Builder.CreateRet(ReturnCode); | 
|  | 79 | return Result; | 
|  | 80 | } | 
|  | 81 |  | 
|  | 82 | // Inserts a function named 'main' that returns a uint32_t: | 
|  | 83 | //    int32_t main() { return X; } | 
|  | 84 | // where X is given by returnCode | 
|  | 85 | Function *insertMainFunction(Module *M, uint32_t returnCode) { | 
|  | 86 | Function *Result = startFunction<int32_t(void)>(M, "main"); | 
|  | 87 |  | 
|  | 88 | Value *ReturnVal = ConstantInt::get(Context, APInt(32, returnCode)); | 
|  | 89 | endFunctionWithRet(Result, ReturnVal); | 
|  | 90 |  | 
|  | 91 | return Result; | 
|  | 92 | } | 
|  | 93 |  | 
|  | 94 | // Inserts a function | 
|  | 95 | //    int32_t add(int32_t a, int32_t b) { return a + b; } | 
|  | 96 | // in the current module and returns a pointer to it. | 
|  | 97 | Function *insertAddFunction(Module *M, StringRef Name = "add") { | 
|  | 98 | Function *Result = startFunction<int32_t(int32_t, int32_t)>(M, Name); | 
|  | 99 |  | 
|  | 100 | Function::arg_iterator args = Result->arg_begin(); | 
|  | 101 | Value *Arg1 = args; | 
|  | 102 | Value *Arg2 = ++args; | 
|  | 103 | Value *AddResult = Builder.CreateAdd(Arg1, Arg2); | 
|  | 104 |  | 
|  | 105 | endFunctionWithRet(Result, AddResult); | 
|  | 106 |  | 
|  | 107 | return Result; | 
|  | 108 | } | 
|  | 109 |  | 
|  | 110 | // Inserts an declaration to a function defined elsewhere | 
|  | 111 | Function *insertExternalReferenceToFunction(Module *M, StringRef Name, | 
|  | 112 | FunctionType *FuncTy) { | 
|  | 113 | Function *Result = Function::Create(FuncTy, | 
|  | 114 | GlobalValue::ExternalLinkage, | 
|  | 115 | Name, M); | 
|  | 116 | return Result; | 
|  | 117 | } | 
|  | 118 |  | 
|  | 119 | // Inserts an declaration to a function defined elsewhere | 
|  | 120 | Function *insertExternalReferenceToFunction(Module *M, Function *Func) { | 
|  | 121 | Function *Result = Function::Create(Func->getFunctionType(), | 
| Andrew Kaylor | 6bbb2c9 | 2013-10-01 01:48:36 +0000 | [diff] [blame] | 122 | GlobalValue::ExternalLinkage, | 
| Andrew Kaylor | 5e7d792 | 2012-10-04 20:29:44 +0000 | [diff] [blame] | 123 | Func->getName(), M); | 
|  | 124 | return Result; | 
|  | 125 | } | 
|  | 126 |  | 
|  | 127 | // Inserts a global variable of type int32 | 
| Andrew Kaylor | 6bbb2c9 | 2013-10-01 01:48:36 +0000 | [diff] [blame] | 128 | // FIXME: make this a template function to support any type | 
| Andrew Kaylor | 5e7d792 | 2012-10-04 20:29:44 +0000 | [diff] [blame] | 129 | GlobalVariable *insertGlobalInt32(Module *M, | 
|  | 130 | StringRef name, | 
|  | 131 | int32_t InitialValue) { | 
|  | 132 | Type *GlobalTy = TypeBuilder<types::i<32>, true>::get(Context); | 
|  | 133 | Constant *IV = ConstantInt::get(Context, APInt(32, InitialValue)); | 
|  | 134 | GlobalVariable *Global = new GlobalVariable(*M, | 
|  | 135 | GlobalTy, | 
|  | 136 | false, | 
|  | 137 | GlobalValue::ExternalLinkage, | 
|  | 138 | IV, | 
|  | 139 | name); | 
|  | 140 | return Global; | 
|  | 141 | } | 
| Andrew Kaylor | 6bbb2c9 | 2013-10-01 01:48:36 +0000 | [diff] [blame] | 142 |  | 
|  | 143 | // Inserts a function | 
|  | 144 | //   int32_t recursive_add(int32_t num) { | 
|  | 145 | //     if (num == 0) { | 
|  | 146 | //       return num; | 
|  | 147 | //     } else { | 
|  | 148 | //       int32_t recursive_param = num - 1; | 
|  | 149 | //       return num + Helper(recursive_param); | 
|  | 150 | //     } | 
|  | 151 | //   } | 
|  | 152 | // NOTE: if Helper is left as the default parameter, Helper == recursive_add. | 
|  | 153 | Function *insertAccumulateFunction(Module *M, | 
|  | 154 | Function *Helper = 0, | 
|  | 155 | StringRef Name = "accumulate") { | 
|  | 156 | Function *Result = startFunction<int32_t(int32_t)>(M, Name); | 
|  | 157 | if (Helper == 0) | 
|  | 158 | Helper = Result; | 
|  | 159 |  | 
|  | 160 | BasicBlock *BaseCase = BasicBlock::Create(Context, "", Result); | 
|  | 161 | BasicBlock *RecursiveCase = BasicBlock::Create(Context, "", Result); | 
|  | 162 |  | 
|  | 163 | // if (num == 0) | 
|  | 164 | Value *Param = Result->arg_begin(); | 
|  | 165 | Value *Zero = ConstantInt::get(Context, APInt(32, 0)); | 
|  | 166 | Builder.CreateCondBr(Builder.CreateICmpEQ(Param, Zero), | 
|  | 167 | BaseCase, RecursiveCase); | 
|  | 168 |  | 
|  | 169 | //   return num; | 
|  | 170 | Builder.SetInsertPoint(BaseCase); | 
|  | 171 | Builder.CreateRet(Param); | 
|  | 172 |  | 
|  | 173 | //   int32_t recursive_param = num - 1; | 
|  | 174 | //   return Helper(recursive_param); | 
|  | 175 | Builder.SetInsertPoint(RecursiveCase); | 
|  | 176 | Value *One = ConstantInt::get(Context, APInt(32, 1)); | 
|  | 177 | Value *RecursiveParam = Builder.CreateSub(Param, One); | 
|  | 178 | Value *RecursiveReturn = Builder.CreateCall(Helper, RecursiveParam); | 
|  | 179 | Value *Accumulator = Builder.CreateAdd(Param, RecursiveReturn); | 
|  | 180 | Builder.CreateRet(Accumulator); | 
|  | 181 |  | 
|  | 182 | return Result; | 
|  | 183 | } | 
|  | 184 |  | 
|  | 185 | // Populates Modules A and B: | 
|  | 186 | // Module A { Extern FB1, Function FA which calls FB1 }, | 
|  | 187 | // Module B { Extern FA, Function FB1, Function FB2 which calls FA }, | 
|  | 188 | void createCrossModuleRecursiveCase(OwningPtr<Module> &A, | 
|  | 189 | Function *&FA, | 
|  | 190 | OwningPtr<Module> &B, | 
|  | 191 | Function *&FB1, | 
|  | 192 | Function *&FB2) { | 
|  | 193 | // Define FB1 in B. | 
|  | 194 | B.reset(createEmptyModule("B")); | 
|  | 195 | FB1 = insertAccumulateFunction(B.get(), 0, "FB1"); | 
|  | 196 |  | 
|  | 197 | // Declare FB1 in A (as an external). | 
|  | 198 | A.reset(createEmptyModule("A")); | 
|  | 199 | Function *FB1Extern = insertExternalReferenceToFunction(A.get(), FB1); | 
|  | 200 |  | 
|  | 201 | // Define FA in A (with a call to FB1). | 
|  | 202 | FA = insertAccumulateFunction(A.get(), FB1Extern, "FA"); | 
|  | 203 |  | 
|  | 204 | // Declare FA in B (as an external) | 
|  | 205 | Function *FAExtern = insertExternalReferenceToFunction(B.get(), FA); | 
|  | 206 |  | 
|  | 207 | // Define FB2 in B (with a call to FA) | 
|  | 208 | FB2 = insertAccumulateFunction(B.get(), FAExtern, "FB2"); | 
|  | 209 | } | 
|  | 210 |  | 
|  | 211 | // Module A { Function FA }, | 
|  | 212 | // Module B { Extern FA, Function FB which calls FA }, | 
|  | 213 | // Module C { Extern FB, Function FC which calls FB }, | 
|  | 214 | void createThreeModuleChainedCallsCase(OwningPtr<Module> &A, | 
|  | 215 | Function *&FA, | 
|  | 216 | OwningPtr<Module> &B, | 
|  | 217 | Function *&FB, | 
|  | 218 | OwningPtr<Module> &C, | 
|  | 219 | Function *&FC) { | 
|  | 220 | A.reset(createEmptyModule("A")); | 
|  | 221 | FA = insertAddFunction(A.get()); | 
|  | 222 |  | 
|  | 223 | B.reset(createEmptyModule("B")); | 
|  | 224 | Function *FAExtern_in_B = insertExternalReferenceToFunction(B.get(), FA); | 
|  | 225 | FB = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(B.get(), FAExtern_in_B); | 
|  | 226 |  | 
|  | 227 | C.reset(createEmptyModule("C")); | 
|  | 228 | Function *FBExtern_in_C = insertExternalReferenceToFunction(C.get(), FB); | 
|  | 229 | FC = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(C.get(), FBExtern_in_C); | 
|  | 230 | } | 
|  | 231 |  | 
|  | 232 |  | 
|  | 233 | // Module A { Function FA }, | 
|  | 234 | // Populates Modules A and B: | 
|  | 235 | // Module B { Function FB } | 
|  | 236 | void createTwoModuleCase(OwningPtr<Module> &A, Function *&FA, | 
|  | 237 | OwningPtr<Module> &B, Function *&FB) { | 
|  | 238 | A.reset(createEmptyModule("A")); | 
|  | 239 | FA = insertAddFunction(A.get()); | 
|  | 240 |  | 
|  | 241 | B.reset(createEmptyModule("B")); | 
|  | 242 | FB = insertAddFunction(B.get()); | 
|  | 243 | } | 
|  | 244 |  | 
|  | 245 | // Module A { Function FA }, | 
|  | 246 | // Module B { Extern FA, Function FB which calls FA } | 
|  | 247 | void createTwoModuleExternCase(OwningPtr<Module> &A, Function *&FA, | 
|  | 248 | OwningPtr<Module> &B, Function *&FB) { | 
|  | 249 | A.reset(createEmptyModule("A")); | 
|  | 250 | FA = insertAddFunction(A.get()); | 
|  | 251 |  | 
|  | 252 | B.reset(createEmptyModule("B")); | 
|  | 253 | Function *FAExtern_in_B = insertExternalReferenceToFunction(B.get(), FA); | 
|  | 254 | FB = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(B.get(), | 
|  | 255 | FAExtern_in_B); | 
|  | 256 | } | 
|  | 257 |  | 
|  | 258 | // Module A { Function FA }, | 
|  | 259 | // Module B { Extern FA, Function FB which calls FA }, | 
|  | 260 | // Module C { Extern FB, Function FC which calls FA }, | 
|  | 261 | void createThreeModuleCase(OwningPtr<Module> &A, | 
|  | 262 | Function *&FA, | 
|  | 263 | OwningPtr<Module> &B, | 
|  | 264 | Function *&FB, | 
|  | 265 | OwningPtr<Module> &C, | 
|  | 266 | Function *&FC) { | 
|  | 267 | A.reset(createEmptyModule("A")); | 
|  | 268 | FA = insertAddFunction(A.get()); | 
|  | 269 |  | 
|  | 270 | B.reset(createEmptyModule("B")); | 
|  | 271 | Function *FAExtern_in_B = insertExternalReferenceToFunction(B.get(), FA); | 
|  | 272 | FB = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(B.get(), FAExtern_in_B); | 
|  | 273 |  | 
|  | 274 | C.reset(createEmptyModule("C")); | 
|  | 275 | Function *FAExtern_in_C = insertExternalReferenceToFunction(C.get(), FA); | 
|  | 276 | FC = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(C.get(), FAExtern_in_C); | 
|  | 277 | } | 
| Daniel Malea | 4146b04 | 2013-06-28 20:37:20 +0000 | [diff] [blame] | 278 | }; | 
|  | 279 |  | 
| Andrew Kaylor | 6bbb2c9 | 2013-10-01 01:48:36 +0000 | [diff] [blame] | 280 |  | 
| Daniel Malea | 4146b04 | 2013-06-28 20:37:20 +0000 | [diff] [blame] | 281 | class MCJITTestBase : public MCJITTestAPICommon, public TrivialModuleBuilder { | 
|  | 282 | protected: | 
| Andrew Kaylor | 6bbb2c9 | 2013-10-01 01:48:36 +0000 | [diff] [blame] | 283 |  | 
| Daniel Malea | 4146b04 | 2013-06-28 20:37:20 +0000 | [diff] [blame] | 284 | MCJITTestBase() | 
|  | 285 | : TrivialModuleBuilder(HostTriple) | 
|  | 286 | , OptLevel(CodeGenOpt::None) | 
|  | 287 | , RelocModel(Reloc::Default) | 
|  | 288 | , CodeModel(CodeModel::Default) | 
|  | 289 | , MArch("") | 
|  | 290 | , MM(new SectionMemoryManager) | 
|  | 291 | { | 
|  | 292 | // The architectures below are known to be compatible with MCJIT as they | 
|  | 293 | // are copied from test/ExecutionEngine/MCJIT/lit.local.cfg and should be | 
|  | 294 | // kept in sync. | 
|  | 295 | SupportedArchs.push_back(Triple::aarch64); | 
|  | 296 | SupportedArchs.push_back(Triple::arm); | 
| Akira Hatanaka | 2e23624 | 2013-07-24 01:58:40 +0000 | [diff] [blame] | 297 | SupportedArchs.push_back(Triple::mips); | 
|  | 298 | SupportedArchs.push_back(Triple::mipsel); | 
| Daniel Malea | 4146b04 | 2013-06-28 20:37:20 +0000 | [diff] [blame] | 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 | // The operating systems below are known to be incompatible with MCJIT as | 
|  | 310 | // they are copied from the test/ExecutionEngine/MCJIT/lit.local.cfg and | 
|  | 311 | // should be kept in sync. | 
|  | 312 | UnsupportedOSs.push_back(Triple::Cygwin); | 
|  | 313 | UnsupportedOSs.push_back(Triple::Darwin); | 
|  | 314 | } | 
| Andrew Kaylor | 5e7d792 | 2012-10-04 20:29:44 +0000 | [diff] [blame] | 315 |  | 
|  | 316 | void createJIT(Module *M) { | 
|  | 317 |  | 
|  | 318 | // Due to the EngineBuilder constructor, it is required to have a Module | 
|  | 319 | // in order to construct an ExecutionEngine (i.e. MCJIT) | 
|  | 320 | assert(M != 0 && "a non-null Module must be provided to create MCJIT"); | 
|  | 321 |  | 
|  | 322 | EngineBuilder EB(M); | 
|  | 323 | std::string Error; | 
|  | 324 | TheJIT.reset(EB.setEngineKind(EngineKind::JIT) | 
|  | 325 | .setUseMCJIT(true) /* can this be folded into the EngineKind enum? */ | 
| Filip Pizlo | 9bc53e8 | 2013-05-14 19:29:00 +0000 | [diff] [blame] | 326 | .setMCJITMemoryManager(MM) | 
| Andrew Kaylor | 5e7d792 | 2012-10-04 20:29:44 +0000 | [diff] [blame] | 327 | .setErrorStr(&Error) | 
|  | 328 | .setOptLevel(CodeGenOpt::None) | 
|  | 329 | .setAllocateGVsWithCode(false) /*does this do anything?*/ | 
|  | 330 | .setCodeModel(CodeModel::JITDefault) | 
|  | 331 | .setRelocationModel(Reloc::Default) | 
|  | 332 | .setMArch(MArch) | 
|  | 333 | .setMCPU(sys::getHostCPUName()) | 
|  | 334 | //.setMAttrs(MAttrs) | 
|  | 335 | .create()); | 
|  | 336 | // At this point, we cannot modify the module any more. | 
|  | 337 | assert(TheJIT.get() != NULL && "error creating MCJIT with EngineBuilder"); | 
|  | 338 | } | 
|  | 339 |  | 
| Andrew Kaylor | 5e7d792 | 2012-10-04 20:29:44 +0000 | [diff] [blame] | 340 | CodeGenOpt::Level OptLevel; | 
|  | 341 | Reloc::Model RelocModel; | 
|  | 342 | CodeModel::Model CodeModel; | 
|  | 343 | StringRef MArch; | 
|  | 344 | SmallVector<std::string, 1> MAttrs; | 
| Andrew Kaylor | 5e7d792 | 2012-10-04 20:29:44 +0000 | [diff] [blame] | 345 | OwningPtr<ExecutionEngine> TheJIT; | 
| Filip Pizlo | 9bc53e8 | 2013-05-14 19:29:00 +0000 | [diff] [blame] | 346 | RTDyldMemoryManager *MM; | 
| Andrew Kaylor | 5e7d792 | 2012-10-04 20:29:44 +0000 | [diff] [blame] | 347 |  | 
| Andrew Kaylor | 5e7d792 | 2012-10-04 20:29:44 +0000 | [diff] [blame] | 348 | OwningPtr<Module> M; | 
|  | 349 | }; | 
|  | 350 |  | 
|  | 351 | } // namespace llvm | 
|  | 352 |  | 
|  | 353 | #endif // MCJIT_TEST_H |