X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FExecutionEngine%2FJIT%2FJIT.cpp;h=616a66e18a4bc880f5a3b31332a940989665ce3f;hb=f451cb870efcf9e0302d25ed05f4cac6bb494e42;hp=81be38bce51089ba4db40db7bb43e254624f74b6;hpb=4b1511b027ce0b648b3379f2891816c25b46f515;p=oota-llvm.git diff --git a/lib/ExecutionEngine/JIT/JIT.cpp b/lib/ExecutionEngine/JIT/JIT.cpp index 81be38bce51..616a66e18a4 100644 --- a/lib/ExecutionEngine/JIT/JIT.cpp +++ b/lib/ExecutionEngine/JIT/JIT.cpp @@ -18,7 +18,6 @@ #include "llvm/Function.h" #include "llvm/GlobalVariable.h" #include "llvm/Instructions.h" -#include "llvm/ModuleProvider.h" #include "llvm/CodeGen/JITCodeEmitter.h" #include "llvm/CodeGen/MachineCodeInfo.h" #include "llvm/ExecutionEngine/GenericValue.h" @@ -172,7 +171,7 @@ void DarwinRegisterFrame(void* FrameBegin) { ob->encoding.i = 0; ob->encoding.b.encoding = llvm::dwarf::DW_EH_PE_omit; - // Put the info on both places, as libgcc uses the first or the the second + // Put the info on both places, as libgcc uses the first or the second // field. Note that we rely on having two pointers here. If fde_end was a // char, things would get complicated. ob->fde_end = (char*)LOI->unseenObjects; @@ -193,32 +192,44 @@ void DarwinRegisterFrame(void* FrameBegin) { /// createJIT - This is the factory method for creating a JIT for the current /// machine, it does not fall back to the interpreter. This takes ownership -/// of the module provider. -ExecutionEngine *ExecutionEngine::createJIT(ModuleProvider *MP, +/// of the module. +ExecutionEngine *ExecutionEngine::createJIT(Module *M, std::string *ErrorStr, JITMemoryManager *JMM, CodeGenOpt::Level OptLevel, - bool GVsWithCode) { - return JIT::createJIT(MP, ErrorStr, JMM, OptLevel, GVsWithCode); + bool GVsWithCode, + CodeModel::Model CMM) { + // Use the defaults for extra parameters. Users can use EngineBuilder to + // set them. + StringRef MArch = ""; + StringRef MCPU = ""; + SmallVector MAttrs; + return JIT::createJIT(M, ErrorStr, JMM, OptLevel, GVsWithCode, CMM, + MArch, MCPU, MAttrs); } -ExecutionEngine *JIT::createJIT(ModuleProvider *MP, +ExecutionEngine *JIT::createJIT(Module *M, std::string *ErrorStr, JITMemoryManager *JMM, CodeGenOpt::Level OptLevel, - bool GVsWithCode) { + bool GVsWithCode, + CodeModel::Model CMM, + StringRef MArch, + StringRef MCPU, + const SmallVectorImpl& MAttrs) { // Make sure we can resolve symbols in the program as well. The zero arg // to the function tells DynamicLibrary to load the program, not a library. if (sys::DynamicLibrary::LoadLibraryPermanently(0, ErrorStr)) return 0; // Pick a target either via -march or by guessing the native arch. - TargetMachine *TM = JIT::selectTarget(MP, ErrorStr); + TargetMachine *TM = JIT::selectTarget(M, MArch, MCPU, MAttrs, ErrorStr); if (!TM || (ErrorStr && ErrorStr->length() > 0)) return 0; + TM->setCodeModel(CMM); // If the target supports JIT code generation, create a the JIT. if (TargetJITInfo *TJ = TM->getJITInfo()) { - return new JIT(MP, *TM, *TJ, JMM, OptLevel, GVsWithCode); + return new JIT(M, *TM, *TJ, JMM, OptLevel, GVsWithCode); } else { if (ErrorStr) *ErrorStr = "target does not support JIT code generation"; @@ -226,15 +237,15 @@ ExecutionEngine *JIT::createJIT(ModuleProvider *MP, } } -JIT::JIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji, +JIT::JIT(Module *M, TargetMachine &tm, TargetJITInfo &tji, JITMemoryManager *JMM, CodeGenOpt::Level OptLevel, bool GVsWithCode) - : ExecutionEngine(MP), TM(tm), TJI(tji), AllocateGVsWithCode(GVsWithCode) { + : ExecutionEngine(M), TM(tm), TJI(tji), AllocateGVsWithCode(GVsWithCode) { setTargetData(TM.getTargetData()); - jitstate = new JITState(MP); + jitstate = new JITState(M); // Initialize JCE - JCE = createEmitter(*this, JMM); + JCE = createEmitter(*this, JMM, TM); // Add target data MutexGuard locked(lock); @@ -275,16 +286,15 @@ JIT::~JIT() { delete &TM; } -/// addModuleProvider - Add a new ModuleProvider to the JIT. If we previously -/// removed the last ModuleProvider, we need re-initialize jitstate with a valid -/// ModuleProvider. -void JIT::addModuleProvider(ModuleProvider *MP) { +/// addModule - Add a new Module to the JIT. If we previously removed the last +/// Module, we need re-initialize jitstate with a valid Module. +void JIT::addModule(Module *M) { MutexGuard locked(lock); if (Modules.empty()) { assert(!jitstate && "jitstate should be NULL if Modules vector is empty!"); - jitstate = new JITState(MP); + jitstate = new JITState(M); FunctionPassManager &PM = jitstate->getPM(locked); PM.add(new TargetData(*TM.getTargetData())); @@ -299,18 +309,17 @@ void JIT::addModuleProvider(ModuleProvider *MP) { PM.doInitialization(); } - ExecutionEngine::addModuleProvider(MP); + ExecutionEngine::addModule(M); } -/// removeModuleProvider - If we are removing the last ModuleProvider, -/// invalidate the jitstate since the PassManager it contains references a -/// released ModuleProvider. -Module *JIT::removeModuleProvider(ModuleProvider *MP, std::string *E) { - Module *result = ExecutionEngine::removeModuleProvider(MP, E); +/// removeModule - If we are removing the last Module, invalidate the jitstate +/// since the PassManager it contains references a released Module. +bool JIT::removeModule(Module *M) { + bool result = ExecutionEngine::removeModule(M); MutexGuard locked(lock); - if (jitstate->getMP() == MP) { + if (jitstate->getModule() == M) { delete jitstate; jitstate = 0; } @@ -333,42 +342,11 @@ Module *JIT::removeModuleProvider(ModuleProvider *MP, std::string *E) { return result; } -/// deleteModuleProvider - Remove a ModuleProvider from the list of modules, -/// and deletes the ModuleProvider and owned Module. Avoids materializing -/// the underlying module. -void JIT::deleteModuleProvider(ModuleProvider *MP, std::string *E) { - ExecutionEngine::deleteModuleProvider(MP, E); - - MutexGuard locked(lock); - - if (jitstate->getMP() == MP) { - delete jitstate; - jitstate = 0; - } - - if (!jitstate && !Modules.empty()) { - jitstate = new JITState(Modules[0]); - - FunctionPassManager &PM = jitstate->getPM(locked); - PM.add(new TargetData(*TM.getTargetData())); - - // Turn the machine code intermediate representation into bytes in memory - // that may be executed. - if (TM.addPassesToEmitMachineCode(PM, *JCE, CodeGenOpt::Default)) { - llvm_report_error("Target does not support machine code emission!"); - } - - // Initialize passes. - PM.doInitialization(); - } -} - /// run - Start execution with the specified function and arguments. /// GenericValue JIT::runFunction(Function *F, const std::vector &ArgValues) { assert(F && "Function *F was null at entry to run()"); - LLVMContext *Context = F->getContext(); void *FPtr = getPointerToFunction(F); assert(FPtr && "Pointer to fn's code was null after getPointerToFunction"); @@ -383,10 +361,10 @@ GenericValue JIT::runFunction(Function *F, // Handle some common cases first. These cases correspond to common `main' // prototypes. - if (RetTy == Type::Int32Ty || RetTy == Type::VoidTy) { + if (RetTy->isInteger(32) || RetTy->isVoidTy()) { switch (ArgValues.size()) { case 3: - if (FTy->getParamType(0) == Type::Int32Ty && + if (FTy->getParamType(0)->isInteger(32) && isa(FTy->getParamType(1)) && isa(FTy->getParamType(2))) { int (*PF)(int, char **, const char **) = @@ -401,7 +379,7 @@ GenericValue JIT::runFunction(Function *F, } break; case 2: - if (FTy->getParamType(0) == Type::Int32Ty && + if (FTy->getParamType(0)->isInteger(32) && isa(FTy->getParamType(1))) { int (*PF)(int, char **) = (int(*)(int, char **))(intptr_t)FPtr; @@ -414,7 +392,7 @@ GenericValue JIT::runFunction(Function *F, break; case 1: if (FTy->getNumParams() == 1 && - FTy->getParamType(0) == Type::Int32Ty) { + FTy->getParamType(0)->isInteger(32)) { GenericValue rv; int (*PF)(int) = (int(*)(int))(intptr_t)FPtr; rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue())); @@ -470,12 +448,12 @@ GenericValue JIT::runFunction(Function *F, // arguments. Make this function and return. // First, create the function. - FunctionType *STy=Context->getFunctionType(RetTy, false); + FunctionType *STy=FunctionType::get(RetTy, false); Function *Stub = Function::Create(STy, Function::InternalLinkage, "", F->getParent()); // Insert a basic block. - BasicBlock *StubBB = BasicBlock::Create("", Stub); + BasicBlock *StubBB = BasicBlock::Create(F->getContext(), "", Stub); // Convert all of the GenericValue arguments over to constants. Note that we // currently don't support varargs. @@ -487,27 +465,29 @@ GenericValue JIT::runFunction(Function *F, switch (ArgTy->getTypeID()) { default: llvm_unreachable("Unknown argument type for function call!"); case Type::IntegerTyID: - C = Context->getConstantInt(AV.IntVal); + C = ConstantInt::get(F->getContext(), AV.IntVal); break; case Type::FloatTyID: - C = Context->getConstantFP(APFloat(AV.FloatVal)); + C = ConstantFP::get(F->getContext(), APFloat(AV.FloatVal)); break; case Type::DoubleTyID: - C = Context->getConstantFP(APFloat(AV.DoubleVal)); + C = ConstantFP::get(F->getContext(), APFloat(AV.DoubleVal)); break; case Type::PPC_FP128TyID: case Type::X86_FP80TyID: case Type::FP128TyID: - C = Context->getConstantFP(APFloat(AV.IntVal)); + C = ConstantFP::get(F->getContext(), APFloat(AV.IntVal)); break; case Type::PointerTyID: void *ArgPtr = GVTOP(AV); if (sizeof(void*) == 4) - C = Context->getConstantInt(Type::Int32Ty, (int)(intptr_t)ArgPtr); + C = ConstantInt::get(Type::getInt32Ty(F->getContext()), + (int)(intptr_t)ArgPtr); else - C = Context->getConstantInt(Type::Int64Ty, (intptr_t)ArgPtr); + C = ConstantInt::get(Type::getInt64Ty(F->getContext()), + (intptr_t)ArgPtr); // Cast the integer to pointer - C = Context->getConstantExprIntToPtr(C, ArgTy); + C = ConstantExpr::getIntToPtr(C, ArgTy); break; } Args.push_back(C); @@ -517,10 +497,11 @@ GenericValue JIT::runFunction(Function *F, "", StubBB); TheCall->setCallingConv(F->getCallingConv()); TheCall->setTailCall(); - if (TheCall->getType() != Type::VoidTy) - ReturnInst::Create(TheCall, StubBB); // Return result of the call. + if (!TheCall->getType()->isVoidTy()) + // Return result of the call. + ReturnInst::Create(F->getContext(), TheCall, StubBB); else - ReturnInst::Create(StubBB); // Just return void. + ReturnInst::Create(F->getContext(), StubBB); // Just return void. // Finally, return the value returned by our nullary stub function. return runFunction(Stub, std::vector()); @@ -553,10 +534,10 @@ void JIT::NotifyFunctionEmitted( } } -void JIT::NotifyFreeingMachineCode(const Function &F, void *OldPtr) { +void JIT::NotifyFreeingMachineCode(void *OldPtr) { MutexGuard locked(lock); for (unsigned I = 0, S = EventListeners.size(); I < S; ++I) { - EventListeners[I]->NotifyFreeingMachineCode(F, OldPtr); + EventListeners[I]->NotifyFreeingMachineCode(OldPtr); } } @@ -579,11 +560,13 @@ void JIT::runJITOnFunction(Function *F, MachineCodeInfo *MCI) { } }; MCIListener MCIL(MCI); - RegisterJITEventListener(&MCIL); + if (MCI) + RegisterJITEventListener(&MCIL); runJITOnFunctionUnlocked(F, locked); - UnregisterJITEventListener(&MCIL); + if (MCI) + UnregisterJITEventListener(&MCIL); } void JIT::runJITOnFunctionUnlocked(Function *F, const MutexGuard &locked) { @@ -596,11 +579,14 @@ void JIT::runJITOnFunctionUnlocked(Function *F, const MutexGuard &locked) { isAlreadyCodeGenerating = false; // If the function referred to another function that had not yet been - // read from bitcode, but we are jitting non-lazily, emit it now. + // read from bitcode, and we are jitting non-lazily, emit it now. while (!jitstate->getPendingFunctions(locked).empty()) { Function *PF = jitstate->getPendingFunctions(locked).back(); jitstate->getPendingFunctions(locked).pop_back(); + assert(!PF->hasAvailableExternallyLinkage() && + "Externally-defined function should not be in pending list."); + // JIT the function isAlreadyCodeGenerating = true; jitstate->getPM(locked).run(*PF); @@ -610,11 +596,6 @@ void JIT::runJITOnFunctionUnlocked(Function *F, const MutexGuard &locked) { // the stub with real address of the function. updateFunctionStub(PF); } - - // If the JIT is configured to emit info so that dlsym can be used to - // rewrite stubs to external globals, do so now. - if (areDlsymStubsEnabled() && isLazyCompilationDisabled()) - updateDlsymStubTable(); } /// getPointerToFunction - This method is used to get the address of the @@ -626,39 +607,21 @@ void *JIT::getPointerToFunction(Function *F) { return Addr; // Check if function already code gen'd MutexGuard locked(lock); - - // Now that this thread owns the lock, check if another thread has already - // code gen'd the function. - if (void *Addr = getPointerToGlobalIfAvailable(F)) - return Addr; - - // Make sure we read in the function if it exists in this Module. - if (F->hasNotBeenReadFromBitcode()) { - // Determine the module provider this function is provided by. - Module *M = F->getParent(); - ModuleProvider *MP = 0; - for (unsigned i = 0, e = Modules.size(); i != e; ++i) { - if (Modules[i]->getModule() == M) { - MP = Modules[i]; - break; - } - } - assert(MP && "Function isn't in a module we know about!"); - - std::string ErrorMsg; - if (MP->materializeFunction(F, &ErrorMsg)) { - llvm_report_error("Error reading function '" + F->getName()+ - "' from bitcode file: " + ErrorMsg); - } - // Now retry to get the address. - if (void *Addr = getPointerToGlobalIfAvailable(F)) - return Addr; + // Now that this thread owns the lock, make sure we read in the function if it + // exists in this Module. + std::string ErrorMsg; + if (F->Materialize(&ErrorMsg)) { + llvm_report_error("Error reading function '" + F->getName()+ + "' from bitcode file: " + ErrorMsg); } - if (F->isDeclaration()) { - bool AbortOnFailure = - !areDlsymStubsEnabled() && !F->hasExternalWeakLinkage(); + // ... and check if another thread has already code gen'd the function. + if (void *Addr = getPointerToGlobalIfAvailable(F)) + return Addr; + + if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) { + bool AbortOnFailure = !F->hasExternalWeakLinkage(); void *Addr = getPointerToNamedFunction(F->getName(), AbortOnFailure); addGlobalMapping(F, Addr); return Addr; @@ -681,13 +644,13 @@ void *JIT::getOrEmitGlobalVariable(const GlobalVariable *GV) { if (Ptr) return Ptr; // If the global is external, just remember the address. - if (GV->isDeclaration()) { + if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) { #if HAVE___DSO_HANDLE if (GV->getName() == "__dso_handle") return (void*)&__dso_handle; #endif - Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(GV->getName().c_str()); - if (Ptr == 0 && !areDlsymStubsEnabled()) { + Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(GV->getName()); + if (Ptr == 0) { llvm_report_error("Could not resolve external global address: " +GV->getName()); }