| //===---------------- JIT.cc - Initialize the JIT -------------------------===// |
| // |
| // The Micro Virtual Machine |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include <llvm/CallingConv.h> |
| #include <llvm/Constants.h> |
| #include <llvm/DerivedTypes.h> |
| #include <llvm/Instructions.h> |
| #include <llvm/LinkAllPasses.h> |
| #include <llvm/LLVMContext.h> |
| #include <llvm/Module.h> |
| #include <llvm/ModuleProvider.h> |
| #include <llvm/PassManager.h> |
| #include <llvm/Type.h> |
| #include <llvm/Analysis/LoopPass.h> |
| #include <llvm/Analysis/Verifier.h> |
| #include <llvm/Config/config.h> |
| #include <llvm/ExecutionEngine/ExecutionEngine.h> |
| #include <llvm/Support/MutexGuard.h> |
| #include <llvm/Target/TargetData.h> |
| #include <llvm/Target/TargetMachine.h> |
| #include <llvm/Target/TargetOptions.h> |
| #include <llvm/Target/TargetSelect.h> |
| |
| #include "mvm/JIT.h" |
| #include "mvm/Threads/Locks.h" |
| #include "mvm/Threads/Thread.h" |
| |
| using namespace mvm; |
| using namespace llvm; |
| |
| |
| namespace mvm { |
| namespace llvm_runtime { |
| #include "LLVMRuntime.inc" |
| } |
| } |
| |
| const char* MvmModule::getHostTriple() { |
| return LLVM_HOSTTRIPLE; |
| } |
| |
| |
| void MvmModule::initialise(CodeGenOpt::Level level, Module* M, |
| TargetMachine* T) { |
| |
| llvm_start_multithreaded(); |
| |
| llvm::NoFramePointerElim = true; |
| llvm::DisablePrettyStackTrace = true; |
| #if DWARF_EXCEPTIONS |
| llvm::DwarfExceptionHandling = true; |
| #else |
| llvm::DwarfExceptionHandling = false; |
| #endif |
| if (!M) { |
| globalModule = new Module("bootstrap module", getGlobalContext()); |
| globalModuleProvider = new ExistingModuleProvider (globalModule); |
| |
| InitializeNativeTarget(); |
| |
| executionEngine = ExecutionEngine::createJIT(globalModuleProvider, 0, |
| 0, level); |
| |
| std::string str = |
| executionEngine->getTargetData()->getStringRepresentation(); |
| globalModule->setDataLayout(str); |
| globalModule->setTargetTriple(getHostTriple()); |
| |
| TheTargetData = executionEngine->getTargetData(); |
| } else { |
| globalModule = M; |
| globalModuleProvider = new ExistingModuleProvider (globalModule); |
| TheTargetData = T->getTargetData(); |
| } |
| |
| globalFunctionPasses = new FunctionPassManager(globalModuleProvider); |
| |
| mvm::llvm_runtime::makeLLVMModuleContents(globalModule); |
| |
| LLVMContext& Context = globalModule->getContext(); |
| // Type declaration |
| ptrType = PointerType::getUnqual(Type::getInt8Ty(Context)); |
| ptr32Type = PointerType::getUnqual(Type::getInt32Ty(Context)); |
| ptrPtrType = PointerType::getUnqual(ptrType); |
| pointerSizeType = globalModule->getPointerSize() == Module::Pointer32 ? |
| Type::getInt32Ty(Context) : Type::getInt64Ty(Context); |
| |
| } |
| |
| |
| MvmModule::MvmModule(llvm::Module* module) { |
| |
| module->setDataLayout(globalModule->getDataLayout()); |
| module->setTargetTriple(globalModule->getTargetTriple()); |
| LLVMContext& Context = module->getContext(); |
| |
| // Constant declaration |
| constantLongMinusOne = ConstantInt::get(Type::getInt64Ty(Context), (uint64_t)-1); |
| constantLongZero = ConstantInt::get(Type::getInt64Ty(Context), 0); |
| constantLongOne = ConstantInt::get(Type::getInt64Ty(Context), 1); |
| constantZero = ConstantInt::get(Type::getInt32Ty(Context), 0); |
| constantInt8Zero = ConstantInt::get(Type::getInt8Ty(Context), 0); |
| constantOne = ConstantInt::get(Type::getInt32Ty(Context), 1); |
| constantTwo = ConstantInt::get(Type::getInt32Ty(Context), 2); |
| constantThree = ConstantInt::get(Type::getInt32Ty(Context), 3); |
| constantFour = ConstantInt::get(Type::getInt32Ty(Context), 4); |
| constantFive = ConstantInt::get(Type::getInt32Ty(Context), 5); |
| constantSix = ConstantInt::get(Type::getInt32Ty(Context), 6); |
| constantSeven = ConstantInt::get(Type::getInt32Ty(Context), 7); |
| constantEight = ConstantInt::get(Type::getInt32Ty(Context), 8); |
| constantMinusOne = ConstantInt::get(Type::getInt32Ty(Context), (uint64_t)-1); |
| constantMinInt = ConstantInt::get(Type::getInt32Ty(Context), MinInt); |
| constantMaxInt = ConstantInt::get(Type::getInt32Ty(Context), MaxInt); |
| constantMinLong = ConstantInt::get(Type::getInt64Ty(Context), MinLong); |
| constantMaxLong = ConstantInt::get(Type::getInt64Ty(Context), MaxLong); |
| constantFloatZero = ConstantFP::get(Type::getFloatTy(Context), 0.0f); |
| constantFloatOne = ConstantFP::get(Type::getFloatTy(Context), 1.0f); |
| constantFloatTwo = ConstantFP::get(Type::getFloatTy(Context), 2.0f); |
| constantDoubleZero = ConstantFP::get(Type::getDoubleTy(Context), 0.0); |
| constantDoubleOne = ConstantFP::get(Type::getDoubleTy(Context), 1.0); |
| constantMaxIntFloat = ConstantFP::get(Type::getFloatTy(Context), MaxIntFloat); |
| constantMinIntFloat = ConstantFP::get(Type::getFloatTy(Context), MinIntFloat); |
| constantMinLongFloat = ConstantFP::get(Type::getFloatTy(Context), MinLongFloat); |
| constantMinLongDouble = ConstantFP::get(Type::getDoubleTy(Context), MinLongDouble); |
| constantMaxLongFloat = ConstantFP::get(Type::getFloatTy(Context), MaxLongFloat); |
| constantMaxIntDouble = ConstantFP::get(Type::getDoubleTy(Context), MaxIntDouble); |
| constantMinIntDouble = ConstantFP::get(Type::getDoubleTy(Context), MinIntDouble); |
| constantMaxLongDouble = ConstantFP::get(Type::getDoubleTy(Context), MaxLongDouble); |
| constantMaxLongDouble = ConstantFP::get(Type::getDoubleTy(Context), MaxLongDouble); |
| constantFloatInfinity = ConstantFP::get(Type::getFloatTy(Context), MaxFloat); |
| constantFloatMinusInfinity = ConstantFP::get(Type::getFloatTy(Context), MinFloat); |
| constantDoubleInfinity = ConstantFP::get(Type::getDoubleTy(Context), MaxDouble); |
| constantDoubleMinusInfinity = ConstantFP::get(Type::getDoubleTy(Context), MinDouble); |
| constantDoubleMinusZero = ConstantFP::get(Type::getDoubleTy(Context), -0.0); |
| constantFloatMinusZero = ConstantFP::get(Type::getFloatTy(Context), -0.0f); |
| constantThreadIDMask = ConstantInt::get(pointerSizeType, mvm::Thread::IDMask); |
| constantStackOverflowMask = |
| ConstantInt::get(pointerSizeType, mvm::Thread::StackOverflowMask); |
| constantFatMask = ConstantInt::get(pointerSizeType, |
| pointerSizeType == Type::getInt32Ty(Context) ? 0x80000000 : 0x8000000000000000LL); |
| constantPtrOne = ConstantInt::get(pointerSizeType, 1); |
| constantPtrZero = ConstantInt::get(pointerSizeType, 0); |
| |
| constantPtrNull = Constant::getNullValue(ptrType); |
| constantPtrLogSize = |
| ConstantInt::get(Type::getInt32Ty(Context), sizeof(void*) == 8 ? 3 : 2); |
| arrayPtrType = PointerType::getUnqual(ArrayType::get(Type::getInt8Ty(Context), 0)); |
| |
| |
| copyDefinitions(module, globalModule); |
| |
| printFloatLLVM = module->getFunction("printFloat"); |
| printDoubleLLVM = module->getFunction("printDouble"); |
| printLongLLVM = module->getFunction("printLong"); |
| printIntLLVM = module->getFunction("printInt"); |
| printObjectLLVM = module->getFunction("printObject"); |
| |
| unwindResume = module->getFunction("_Unwind_Resume_or_Rethrow"); |
| |
| llvmGetException = module->getFunction("llvm.eh.exception"); |
| exceptionSelector = (module->getPointerSize() == Module::Pointer32 ? |
| module->getFunction("llvm.eh.selector.i32") : |
| module->getFunction("llvm.eh.selector.i64")); |
| |
| personality = module->getFunction("__gxx_personality_v0"); |
| exceptionEndCatch = module->getFunction("__cxa_end_catch"); |
| exceptionBeginCatch = module->getFunction("__cxa_begin_catch"); |
| |
| func_llvm_sqrt_f64 = module->getFunction("llvm.sqrt.f64"); |
| func_llvm_sin_f64 = module->getFunction("llvm.sin.f64"); |
| func_llvm_cos_f64 = module->getFunction("llvm.cos.f64"); |
| |
| func_llvm_tan_f64 = module->getFunction("tan"); |
| func_llvm_asin_f64 = module->getFunction("asin"); |
| func_llvm_acos_f64 = module->getFunction("acos"); |
| func_llvm_atan_f64 = module->getFunction("atan"); |
| func_llvm_exp_f64 = module->getFunction("exp"); |
| func_llvm_log_f64 = module->getFunction("log"); |
| func_llvm_ceil_f64 = module->getFunction("ceil"); |
| func_llvm_floor_f64 = module->getFunction("floor"); |
| func_llvm_cbrt_f64 = module->getFunction("cbrt"); |
| func_llvm_cosh_f64 = module->getFunction("cosh"); |
| func_llvm_expm1_f64 = module->getFunction("expm1"); |
| func_llvm_log10_f64 = module->getFunction("log10"); |
| func_llvm_log1p_f64 = module->getFunction("log1p"); |
| func_llvm_sinh_f64 = module->getFunction("sinh"); |
| func_llvm_tanh_f64 = module->getFunction("tanh"); |
| func_llvm_fabs_f64 = module->getFunction("fabs"); |
| func_llvm_rint_f64 = module->getFunction("rint"); |
| |
| func_llvm_hypot_f64 = module->getFunction("hypot"); |
| func_llvm_pow_f64 = module->getFunction("pow"); |
| func_llvm_atan2_f64 = module->getFunction("atan2"); |
| |
| func_llvm_fabs_f32 = module->getFunction("fabsf"); |
| |
| setjmpLLVM = module->getFunction("setjmp"); |
| |
| llvm_memcpy_i32 = module->getFunction("llvm.memcpy.i32"); |
| llvm_memset_i32 = module->getFunction("llvm.memset.i32"); |
| llvm_frameaddress = module->getFunction("llvm.frameaddress"); |
| llvm_gc_gcroot = module->getFunction("llvm.gcroot"); |
| |
| llvm_atomic_lcs_i8 = module->getFunction("llvm.atomic.cmp.swap.i8.p0i8"); |
| llvm_atomic_lcs_i16 = module->getFunction("llvm.atomic.cmp.swap.i16.p0i16"); |
| llvm_atomic_lcs_i32 = module->getFunction("llvm.atomic.cmp.swap.i32.p0i32"); |
| llvm_atomic_lcs_i64 = module->getFunction("llvm.atomic.cmp.swap.i64.p0i64"); |
| |
| llvm_atomic_lcs_ptr = pointerSizeType == Type::getInt32Ty(Context) ? llvm_atomic_lcs_i32 : |
| llvm_atomic_lcs_i64; |
| |
| unconditionalSafePoint = module->getFunction("unconditionalSafePoint"); |
| conditionalSafePoint = module->getFunction("conditionalSafePoint"); |
| } |
| |
| |
| const llvm::PointerType* MvmModule::ptrType; |
| const llvm::PointerType* MvmModule::ptr32Type; |
| const llvm::PointerType* MvmModule::ptrPtrType; |
| const llvm::Type* MvmModule::pointerSizeType; |
| const llvm::Type* MvmModule::arrayPtrType; |
| |
| const llvm::TargetData* MvmModule::TheTargetData; |
| llvm::Module *MvmModule::globalModule; |
| llvm::ExistingModuleProvider *MvmModule::globalModuleProvider; |
| llvm::FunctionPassManager* MvmModule::globalFunctionPasses; |
| llvm::ExecutionEngine* MvmModule::executionEngine; |
| mvm::LockRecursive MvmModule::protectEngine; |
| |
| |
| uint64 MvmModule::getTypeSize(const llvm::Type* type) { |
| return TheTargetData->getTypeAllocSize(type); |
| } |
| |
| void MvmModule::runPasses(llvm::Function* func, |
| llvm::FunctionPassManager* pm) { |
| // Take the lock because the pass manager will call materializeFunction. |
| // Our implementation of materializeFunction requires that the lock is held |
| // by the caller. This is due to LLVM's JIT subsystem where the call to |
| // materializeFunction is guarded. |
| if (executionEngine) executionEngine->lock.acquire(); |
| pm->run(*func); |
| if (executionEngine) executionEngine->lock.release(); |
| } |
| |
| static void addPass(FunctionPassManager *PM, Pass *P) { |
| // Add the pass to the pass manager... |
| PM->add(P); |
| } |
| |
| // This is equivalent to: |
| // opt -simplifycfg -mem2reg -instcombine -jump-threading -simplifycfg |
| // -scalarrepl -instcombine -condprop -simplifycfg -predsimplify |
| // -reassociate -licm -loop-unswitch -indvars -loop-deletion -loop-unroll |
| // -instcombine -gvn -sccp -simplifycfg -instcombine -condprop -dse -adce |
| // -simplifycfg |
| // |
| void MvmModule::AddStandardCompilePasses() { |
| // TODO: enable this when |
| // - each module will have its declaration of external functions |
| // |
| //PM->add(llvm::createVerifierPass()); // Verify that input is correct |
| |
| FunctionPassManager* PM = globalFunctionPasses; |
| PM->add(new TargetData(*MvmModule::TheTargetData)); |
| |
| addPass(PM, createCFGSimplificationPass()); // Clean up disgusting code |
| addPass(PM, createPromoteMemoryToRegisterPass());// Kill useless allocas |
| |
| addPass(PM, createInstructionCombiningPass()); // Cleanup for scalarrepl. |
| addPass(PM, createJumpThreadingPass()); // Thread jumps. |
| addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs |
| addPass(PM, createScalarReplAggregatesPass()); // Break up aggregate allocas |
| addPass(PM, createInstructionCombiningPass()); // Combine silly seq's |
| addPass(PM, createCondPropagationPass()); // Propagate conditionals |
| |
| addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs |
| addPass(PM, createPredicateSimplifierPass()); |
| addPass(PM, createReassociatePass()); // Reassociate expressions |
| addPass(PM, createLICMPass()); // Hoist loop invariants |
| |
| addPass(PM, createLoopUnswitchPass()); // Unswitch loops. |
| addPass(PM, createIndVarSimplifyPass()); // Canonicalize indvars |
| addPass(PM, createLoopDeletionPass()); // Delete dead loops |
| addPass(PM, createLoopUnrollPass()); // Unroll small loops*/ |
| addPass(PM, createInstructionCombiningPass()); // Clean up after the unroller |
| addPass(PM, createGVNPass()); // Remove redundancies |
| addPass(PM, createSCCPPass()); // Constant prop with SCCP |
| addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs |
| |
| // Run instcombine after redundancy elimination to exploit opportunities |
| // opened up by them. |
| addPass(PM, createInstructionCombiningPass()); |
| addPass(PM, createCondPropagationPass()); // Propagate conditionals |
| |
| addPass(PM, createDeadStoreEliminationPass()); // Delete dead stores |
| addPass(PM, createAggressiveDCEPass()); // Delete dead instructions |
| addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs |
| |
| PM->doInitialization(); |
| |
| } |
| |
| // We protect the creation of IR with the executionEngine lock because |
| // codegen'ing a function may also create IR objects. |
| void MvmModule::protectIR() { |
| if (executionEngine) { |
| protectEngine.lock(); |
| } |
| } |
| |
| void MvmModule::unprotectIR() { |
| if (executionEngine) { |
| protectEngine.unlock(); |
| } |
| } |
| |
| |
| void MvmModule::copyDefinitions(Module* Dst, Module* Src) { |
| // Loop over all of the functions in the src module, mapping them over |
| for (Module::const_iterator I = Src->begin(), E = Src->end(); I != E; ++I) { |
| const Function *SF = I; // SrcFunction |
| assert(SF->isDeclaration() && |
| "Don't know how top copy functions with body"); |
| Function* F = Function::Create(SF->getFunctionType(), |
| GlobalValue::ExternalLinkage, |
| SF->getName(), Dst); |
| F->setAttributes(SF->getAttributes()); |
| } |
| } |