Changes in directory llvm/lib/ExecutionEngine:
ExecutionEngine.cpp updated: 1.83 -> 1.84 --- Log message: initial changes to support JIT'ing from multiple module providers, implicitly linking the program on the fly. --- Diffs of the changes: (+150 -56) ExecutionEngine.cpp | 206 +++++++++++++++++++++++++++++++++++++--------------- 1 files changed, 150 insertions(+), 56 deletions(-) Index: llvm/lib/ExecutionEngine/ExecutionEngine.cpp diff -u llvm/lib/ExecutionEngine/ExecutionEngine.cpp:1.83 llvm/lib/ExecutionEngine/ExecutionEngine.cpp:1.84 --- llvm/lib/ExecutionEngine/ExecutionEngine.cpp:1.83 Sun May 14 14:01:55 2006 +++ llvm/lib/ExecutionEngine/ExecutionEngine.cpp Tue Aug 15 20:24:12 2006 @@ -35,19 +35,33 @@ ExecutionEngine::EECtorFn ExecutionEngine::JITCtor = 0; ExecutionEngine::EECtorFn ExecutionEngine::InterpCtor = 0; -ExecutionEngine::ExecutionEngine(ModuleProvider *P) : - CurMod(*P->getModule()), MP(P) { +ExecutionEngine::ExecutionEngine(ModuleProvider *P) { + Modules.push_back(P); assert(P && "ModuleProvider is null?"); } -ExecutionEngine::ExecutionEngine(Module *M) : CurMod(*M), MP(0) { +ExecutionEngine::ExecutionEngine(Module *M) { assert(M && "Module is null?"); + Modules.push_back(new ExistingModuleProvider(M)); } ExecutionEngine::~ExecutionEngine() { - delete MP; + for (unsigned i = 0, e = Modules.size(); i != e; ++i) + delete Modules[i]; } +/// FindFunctionNamed - Search all of the active modules to find the one that +/// defines FnName. This is very slow operation and shouldn't be used for +/// general code. +Function *ExecutionEngine::FindFunctionNamed(const char *FnName) { + for (unsigned i = 0, e = Modules.size(); i != e; ++i) { + if (Function *F = Modules[i]->getModule()->getNamedFunction(FnName)) + return F; + } + return 0; +} + + /// addGlobalMapping - Tell the execution engine that the specified global is /// at the specified location. This is used internally as functions are JIT'd /// and as global variables are laid out in memory. It can and should also be @@ -168,37 +182,43 @@ /// runStaticConstructorsDestructors - This method is used to execute all of -/// the static constructors or destructors for a module, depending on the +/// the static constructors or destructors for a program, depending on the /// value of isDtors. void ExecutionEngine::runStaticConstructorsDestructors(bool isDtors) { const char *Name = isDtors ? "llvm.global_dtors" : "llvm.global_ctors"; - GlobalVariable *GV = CurMod.getNamedGlobal(Name); - - // If this global has internal linkage, or if it has a use, then it must be - // an old-style (llvmgcc3) static ctor with __main linked in and in use. If - // this is the case, don't execute any of the global ctors, __main will do it. - if (!GV || GV->isExternal() || GV->hasInternalLinkage()) return; - // Should be an array of '{ int, void ()* }' structs. The first value is the - // init priority, which we ignore. - ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer()); - if (!InitList) return; - for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) - if (ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i))){ - if (CS->getNumOperands() != 2) return; // Not array of 2-element structs. + // Execute global ctors/dtors for each module in the program. + for (unsigned m = 0, e = Modules.size(); m != e; ++m) { + GlobalVariable *GV = Modules[m]->getModule()->getNamedGlobal(Name); + + // If this global has internal linkage, or if it has a use, then it must be + // an old-style (llvmgcc3) static ctor with __main linked in and in use. If + // this is the case, don't execute any of the global ctors, __main will do + // it. + if (!GV || GV->isExternal() || GV->hasInternalLinkage()) continue; + + // Should be an array of '{ int, void ()* }' structs. The first value is + // the init priority, which we ignore. + ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer()); + if (!InitList) continue; + for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) + if (ConstantStruct *CS = + dyn_cast<ConstantStruct>(InitList->getOperand(i))) { + if (CS->getNumOperands() != 2) break; // Not array of 2-element structs. - Constant *FP = CS->getOperand(1); - if (FP->isNullValue()) - return; // Found a null terminator, exit. + Constant *FP = CS->getOperand(1); + if (FP->isNullValue()) + break; // Found a null terminator, exit. - if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP)) - if (CE->getOpcode() == Instruction::Cast) - FP = CE->getOperand(0); - if (Function *F = dyn_cast<Function>(FP)) { - // Execute the ctor/dtor function! - runFunction(F, std::vector<GenericValue>()); + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP)) + if (CE->getOpcode() == Instruction::Cast) + FP = CE->getOperand(0); + if (Function *F = dyn_cast<Function>(FP)) { + // Execute the ctor/dtor function! + runFunction(F, std::vector<GenericValue>()); + } } - } + } } /// runFunctionAsMain - This is a helper function which wraps runFunction to @@ -610,36 +630,110 @@ const TargetData *TD = getTargetData(); // Loop over all of the global variables in the program, allocating the memory - // to hold them. - Module &M = getModule(); - for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); - I != E; ++I) - if (!I->isExternal()) { - // Get the type of the global... - const Type *Ty = I->getType()->getElementType(); - - // Allocate some memory for it! - unsigned Size = TD->getTypeSize(Ty); - addGlobalMapping(I, new char[Size]); - } else { - // External variable reference. Try to use the dynamic loader to - // get a pointer to it. - if (void *SymAddr = sys::DynamicLibrary::SearchForAddressOfSymbol( - I->getName().c_str())) - addGlobalMapping(I, SymAddr); - else { - std::cerr << "Could not resolve external global address: " - << I->getName() << "\n"; - abort(); + // to hold them. If there is more than one module, do a prepass over globals + // to figure out how the different modules should link together. + // + std::map<std::pair<std::string, const Type*>, + const GlobalValue*> LinkedGlobalsMap; + + if (Modules.size() != 1) { + for (unsigned m = 0, e = Modules.size(); m != e; ++m) { + Module &M = *Modules[m]->getModule(); + for (Module::const_global_iterator I = M.global_begin(), + E = M.global_end(); I != E; ++I) { + const GlobalValue *GV = I; + if (GV->hasInternalLinkage() || GV->isExternal() || + GV->hasAppendingLinkage() || !GV->hasName()) + continue;// Ignore external globals and globals with internal linkage. + + const GlobalValue *&GVEntry = + LinkedGlobalsMap[std::make_pair(GV->getName(), GV->getType())]; + + // If this is the first time we've seen this global, it is the canonical + // version. + if (!GVEntry) { + GVEntry = GV; + continue; + } + + // If the existing global is strong, never replace it. + if (GVEntry->hasExternalLinkage()) + continue; + + // Otherwise, we know it's linkonce/weak, replace it if this is a strong + // symbol. + if (GV->hasExternalLinkage()) + GVEntry = GV; } } - - // Now that all of the globals are set up in memory, loop through them all and - // initialize their contents. - for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); - I != E; ++I) - if (!I->isExternal()) - EmitGlobalVariable(I); + } + + std::vector<const GlobalValue*> NonCanonicalGlobals; + for (unsigned m = 0, e = Modules.size(); m != e; ++m) { + Module &M = *Modules[m]->getModule(); + for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + // In the multi-module case, see what this global maps to. + if (!LinkedGlobalsMap.empty()) { + if (const GlobalValue *GVEntry = + LinkedGlobalsMap[std::make_pair(I->getName(), I->getType())]) { + // If something else is the canonical global, ignore this one. + if (GVEntry != &*I) { + NonCanonicalGlobals.push_back(I); + continue; + } + } + } + + if (!I->isExternal()) { + // Get the type of the global. + const Type *Ty = I->getType()->getElementType(); + + // Allocate some memory for it! + unsigned Size = TD->getTypeSize(Ty); + addGlobalMapping(I, new char[Size]); + } else { + // External variable reference. Try to use the dynamic loader to + // get a pointer to it. + if (void *SymAddr = + sys::DynamicLibrary::SearchForAddressOfSymbol(I->getName().c_str())) + addGlobalMapping(I, SymAddr); + else { + std::cerr << "Could not resolve external global address: " + << I->getName() << "\n"; + abort(); + } + } + } + + // If there are multiple modules, map the non-canonical globals to their + // canonical location. + if (!NonCanonicalGlobals.empty()) { + for (unsigned i = 0, e = NonCanonicalGlobals.size(); i != e; ++i) { + const GlobalValue *GV = NonCanonicalGlobals[i]; + const GlobalValue *CGV = + LinkedGlobalsMap[std::make_pair(GV->getName(), GV->getType())]; + void *Ptr = getPointerToGlobalIfAvailable(CGV); + assert(Ptr && "Canonical global wasn't codegen'd!"); + addGlobalMapping(GV, getPointerToGlobalIfAvailable(CGV)); + } + } + + // Now that all of the globals are set up in memory, loop through them all and + // initialize their contents. + for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + if (!I->isExternal()) { + if (!LinkedGlobalsMap.empty()) { + if (const GlobalValue *GVEntry = + LinkedGlobalsMap[std::make_pair(I->getName(), I->getType())]) + if (GVEntry != &*I) // Not the canonical variable. + continue; + } + EmitGlobalVariable(I); + } + } + } } // EmitGlobalVariable - This method emits the specified global variable to the _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits