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 30 namespace llvm { 31 32 /// Helper class that can build very simple Modules 33 class TrivialModuleBuilder { 34 protected: 35 LLVMContext Context; 36 IRBuilder<> Builder; 37 std::string BuilderTriple; 38 TrivialModuleBuilder(const std::string & Triple)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> startFunction(Module * M,StringRef Name)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 endFunctionWithRet(Function * Func,Value * RetValue)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> insertSimpleCallFunction(Module * M,Function * Callee)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 insertMainFunction(Module * M,uint32_t 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> insertExternalReferenceToFunction(Module * M,StringRef Name)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 insertExternalReferenceToFunction(Module * M,StringRef Name,FunctionType * FuncTy)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 insertExternalReferenceToFunction(Module * M,Function * Func)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 insertGlobalInt32(Module * M,StringRef name,int32_t InitialValue)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 }, createCrossModuleRecursiveCase(std::unique_ptr<Module> & A,Function * & FA,std::unique_ptr<Module> & B,Function * & FB1,Function * & FB2)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 createThreeModuleChainedCallsCase(std::unique_ptr<Module> & A,Function * & FA,std::unique_ptr<Module> & B,Function * & FB,std::unique_ptr<Module> & C,Function * & FC)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 } createTwoModuleCase(std::unique_ptr<Module> & A,Function * & FA,std::unique_ptr<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 } createTwoModuleExternCase(std::unique_ptr<Module> & A,Function * & FA,std::unique_ptr<Module> & B,Function * & FB)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 }, createThreeModuleCase(std::unique_ptr<Module> & A,Function * & FA,std::unique_ptr<Module> & B,Function * & FB,std::unique_ptr<Module> & C,Function * & FC)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 279 class MCJITTestBase : public MCJITTestAPICommon, public TrivialModuleBuilder { 280 protected: 281 MCJITTestBase()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 createJIT(std::unique_ptr<Module> M)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