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 LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTBASE_H 18 #define LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTBASE_H 19 20 #include "MCJITTestAPICommon.h" 21 #include "llvm/Config/config.h" 22 #include "llvm/ExecutionEngine/ExecutionEngine.h" 23 #include "llvm/ExecutionEngine/SectionMemoryManager.h" 24 #include "llvm/IR/Function.h" 25 #include "llvm/IR/IRBuilder.h" 26 #include "llvm/IR/LLVMContext.h" 27 #include "llvm/IR/Module.h" 28 #include "llvm/IR/TypeBuilder.h" 29 #include "llvm/Support/CodeGen.h" 30 31 namespace llvm { 32 33 /// Helper class that can build very simple Modules 34 class TrivialModuleBuilder { 35 protected: 36 LLVMContext Context; 37 IRBuilder<> Builder; 38 std::string BuilderTriple; 39 TrivialModuleBuilder(const std::string & Triple)40 TrivialModuleBuilder(const std::string &Triple) 41 : Builder(Context), BuilderTriple(Triple) {} 42 43 Module *createEmptyModule(StringRef Name = StringRef()) { 44 Module * M = new Module(Name, Context); 45 M->setTargetTriple(Triple::normalize(BuilderTriple)); 46 return M; 47 } 48 49 template<typename FuncType> startFunction(Module * M,StringRef Name)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 endFunctionWithRet(Function * Func,Value * RetValue)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> insertSimpleCallFunction(Module * M,Function * Callee)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 insertMainFunction(Module * M,uint32_t 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 a declaration to a function defined elsewhere 111 template <typename FuncType> insertExternalReferenceToFunction(Module * M,StringRef Name)112 Function *insertExternalReferenceToFunction(Module *M, StringRef Name) { 113 Function *Result = Function::Create( 114 TypeBuilder<FuncType, false>::get(Context), 115 GlobalValue::ExternalLinkage, Name, M); 116 return Result; 117 } 118 119 // Inserts an declaration to a function defined elsewhere insertExternalReferenceToFunction(Module * M,StringRef Name,FunctionType * FuncTy)120 Function *insertExternalReferenceToFunction(Module *M, StringRef Name, 121 FunctionType *FuncTy) { 122 Function *Result = Function::Create(FuncTy, 123 GlobalValue::ExternalLinkage, 124 Name, M); 125 return Result; 126 } 127 128 // Inserts an declaration to a function defined elsewhere insertExternalReferenceToFunction(Module * M,Function * Func)129 Function *insertExternalReferenceToFunction(Module *M, Function *Func) { 130 Function *Result = Function::Create(Func->getFunctionType(), 131 GlobalValue::ExternalLinkage, 132 Func->getName(), M); 133 return Result; 134 } 135 136 // Inserts a global variable of type int32 137 // FIXME: make this a template function to support any type insertGlobalInt32(Module * M,StringRef name,int32_t InitialValue)138 GlobalVariable *insertGlobalInt32(Module *M, 139 StringRef name, 140 int32_t InitialValue) { 141 Type *GlobalTy = TypeBuilder<types::i<32>, true>::get(Context); 142 Constant *IV = ConstantInt::get(Context, APInt(32, InitialValue)); 143 GlobalVariable *Global = new GlobalVariable(*M, 144 GlobalTy, 145 false, 146 GlobalValue::ExternalLinkage, 147 IV, 148 name); 149 return Global; 150 } 151 152 // Inserts a function 153 // int32_t recursive_add(int32_t num) { 154 // if (num == 0) { 155 // return num; 156 // } else { 157 // int32_t recursive_param = num - 1; 158 // return num + Helper(recursive_param); 159 // } 160 // } 161 // NOTE: if Helper is left as the default parameter, Helper == recursive_add. 162 Function *insertAccumulateFunction(Module *M, 163 Function *Helper = 0, 164 StringRef Name = "accumulate") { 165 Function *Result = startFunction<int32_t(int32_t)>(M, Name); 166 if (Helper == 0) 167 Helper = Result; 168 169 BasicBlock *BaseCase = BasicBlock::Create(Context, "", Result); 170 BasicBlock *RecursiveCase = BasicBlock::Create(Context, "", Result); 171 172 // if (num == 0) 173 Value *Param = Result->arg_begin(); 174 Value *Zero = ConstantInt::get(Context, APInt(32, 0)); 175 Builder.CreateCondBr(Builder.CreateICmpEQ(Param, Zero), 176 BaseCase, RecursiveCase); 177 178 // return num; 179 Builder.SetInsertPoint(BaseCase); 180 Builder.CreateRet(Param); 181 182 // int32_t recursive_param = num - 1; 183 // return Helper(recursive_param); 184 Builder.SetInsertPoint(RecursiveCase); 185 Value *One = ConstantInt::get(Context, APInt(32, 1)); 186 Value *RecursiveParam = Builder.CreateSub(Param, One); 187 Value *RecursiveReturn = Builder.CreateCall(Helper, RecursiveParam); 188 Value *Accumulator = Builder.CreateAdd(Param, RecursiveReturn); 189 Builder.CreateRet(Accumulator); 190 191 return Result; 192 } 193 194 // Populates Modules A and B: 195 // Module A { Extern FB1, Function FA which calls FB1 }, 196 // Module B { Extern FA, Function FB1, Function FB2 which calls FA }, createCrossModuleRecursiveCase(std::unique_ptr<Module> & A,Function * & FA,std::unique_ptr<Module> & B,Function * & FB1,Function * & FB2)197 void createCrossModuleRecursiveCase(std::unique_ptr<Module> &A, Function *&FA, 198 std::unique_ptr<Module> &B, 199 Function *&FB1, Function *&FB2) { 200 // Define FB1 in B. 201 B.reset(createEmptyModule("B")); 202 FB1 = insertAccumulateFunction(B.get(), 0, "FB1"); 203 204 // Declare FB1 in A (as an external). 205 A.reset(createEmptyModule("A")); 206 Function *FB1Extern = insertExternalReferenceToFunction(A.get(), FB1); 207 208 // Define FA in A (with a call to FB1). 209 FA = insertAccumulateFunction(A.get(), FB1Extern, "FA"); 210 211 // Declare FA in B (as an external) 212 Function *FAExtern = insertExternalReferenceToFunction(B.get(), FA); 213 214 // Define FB2 in B (with a call to FA) 215 FB2 = insertAccumulateFunction(B.get(), FAExtern, "FB2"); 216 } 217 218 // Module A { Function FA }, 219 // Module B { Extern FA, Function FB which calls FA }, 220 // Module C { Extern FB, Function FC which calls FB }, 221 void createThreeModuleChainedCallsCase(std::unique_ptr<Module> & A,Function * & FA,std::unique_ptr<Module> & B,Function * & FB,std::unique_ptr<Module> & C,Function * & FC)222 createThreeModuleChainedCallsCase(std::unique_ptr<Module> &A, Function *&FA, 223 std::unique_ptr<Module> &B, Function *&FB, 224 std::unique_ptr<Module> &C, Function *&FC) { 225 A.reset(createEmptyModule("A")); 226 FA = insertAddFunction(A.get()); 227 228 B.reset(createEmptyModule("B")); 229 Function *FAExtern_in_B = insertExternalReferenceToFunction(B.get(), FA); 230 FB = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(B.get(), FAExtern_in_B); 231 232 C.reset(createEmptyModule("C")); 233 Function *FBExtern_in_C = insertExternalReferenceToFunction(C.get(), FB); 234 FC = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(C.get(), FBExtern_in_C); 235 } 236 237 238 // Module A { Function FA }, 239 // Populates Modules A and B: 240 // Module B { Function FB } createTwoModuleCase(std::unique_ptr<Module> & A,Function * & FA,std::unique_ptr<Module> & B,Function * & FB)241 void createTwoModuleCase(std::unique_ptr<Module> &A, Function *&FA, 242 std::unique_ptr<Module> &B, Function *&FB) { 243 A.reset(createEmptyModule("A")); 244 FA = insertAddFunction(A.get()); 245 246 B.reset(createEmptyModule("B")); 247 FB = insertAddFunction(B.get()); 248 } 249 250 // Module A { Function FA }, 251 // Module B { Extern FA, Function FB which calls FA } createTwoModuleExternCase(std::unique_ptr<Module> & A,Function * & FA,std::unique_ptr<Module> & B,Function * & FB)252 void createTwoModuleExternCase(std::unique_ptr<Module> &A, Function *&FA, 253 std::unique_ptr<Module> &B, Function *&FB) { 254 A.reset(createEmptyModule("A")); 255 FA = insertAddFunction(A.get()); 256 257 B.reset(createEmptyModule("B")); 258 Function *FAExtern_in_B = insertExternalReferenceToFunction(B.get(), FA); 259 FB = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(B.get(), 260 FAExtern_in_B); 261 } 262 263 // Module A { Function FA }, 264 // Module B { Extern FA, Function FB which calls FA }, 265 // Module C { Extern FB, Function FC which calls FA }, createThreeModuleCase(std::unique_ptr<Module> & A,Function * & FA,std::unique_ptr<Module> & B,Function * & FB,std::unique_ptr<Module> & C,Function * & FC)266 void createThreeModuleCase(std::unique_ptr<Module> &A, Function *&FA, 267 std::unique_ptr<Module> &B, Function *&FB, 268 std::unique_ptr<Module> &C, Function *&FC) { 269 A.reset(createEmptyModule("A")); 270 FA = insertAddFunction(A.get()); 271 272 B.reset(createEmptyModule("B")); 273 Function *FAExtern_in_B = insertExternalReferenceToFunction(B.get(), FA); 274 FB = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(B.get(), FAExtern_in_B); 275 276 C.reset(createEmptyModule("C")); 277 Function *FAExtern_in_C = insertExternalReferenceToFunction(C.get(), FA); 278 FC = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(C.get(), FAExtern_in_C); 279 } 280 }; 281 282 283 class MCJITTestBase : public MCJITTestAPICommon, public TrivialModuleBuilder { 284 protected: 285 MCJITTestBase()286 MCJITTestBase() 287 : TrivialModuleBuilder(HostTriple) 288 , OptLevel(CodeGenOpt::None) 289 , RelocModel(Reloc::Default) 290 , CodeModel(CodeModel::Default) 291 , MArch("") 292 , MM(new SectionMemoryManager) 293 { 294 // The architectures below are known to be compatible with MCJIT as they 295 // are copied from test/ExecutionEngine/MCJIT/lit.local.cfg and should be 296 // kept in sync. 297 SupportedArchs.push_back(Triple::aarch64); 298 SupportedArchs.push_back(Triple::arm); 299 SupportedArchs.push_back(Triple::mips); 300 SupportedArchs.push_back(Triple::mipsel); 301 SupportedArchs.push_back(Triple::x86); 302 SupportedArchs.push_back(Triple::x86_64); 303 304 // Some architectures have sub-architectures in which tests will fail, like 305 // ARM. These two vectors will define if they do have sub-archs (to avoid 306 // extra work for those who don't), and if so, if they are listed to work 307 HasSubArchs.push_back(Triple::arm); 308 SupportedSubArchs.push_back("armv6"); 309 SupportedSubArchs.push_back("armv7"); 310 311 UnsupportedEnvironments.push_back(Triple::Cygnus); 312 } 313 createJIT(std::unique_ptr<Module> M)314 void createJIT(std::unique_ptr<Module> M) { 315 316 // Due to the EngineBuilder constructor, it is required to have a Module 317 // in order to construct an ExecutionEngine (i.e. MCJIT) 318 assert(M != 0 && "a non-null Module must be provided to create MCJIT"); 319 320 EngineBuilder EB(std::move(M)); 321 std::string Error; 322 TheJIT.reset(EB.setEngineKind(EngineKind::JIT) 323 .setMCJITMemoryManager(std::move(MM)) 324 .setErrorStr(&Error) 325 .setOptLevel(CodeGenOpt::None) 326 .setCodeModel(CodeModel::JITDefault) 327 .setRelocationModel(Reloc::Default) 328 .setMArch(MArch) 329 .setMCPU(sys::getHostCPUName()) 330 //.setMAttrs(MAttrs) 331 .create()); 332 // At this point, we cannot modify the module any more. 333 assert(TheJIT.get() != NULL && "error creating MCJIT with EngineBuilder"); 334 } 335 336 CodeGenOpt::Level OptLevel; 337 Reloc::Model RelocModel; 338 CodeModel::Model CodeModel; 339 StringRef MArch; 340 SmallVector<std::string, 1> MAttrs; 341 std::unique_ptr<ExecutionEngine> TheJIT; 342 std::unique_ptr<RTDyldMemoryManager> MM; 343 344 std::unique_ptr<Module> M; 345 }; 346 347 } // namespace llvm 348 349 #endif 350