aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ExecutionEngine/ExecutionEngine.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2006-08-16 01:24:12 +0000
committerChris Lattner <sabre@nondot.org>2006-08-16 01:24:12 +0000
commitfe854034677f59baca1e38075e71f6efca247a03 (patch)
treefb271b47b99ed66ee0ac9f890b9d7bcfddc02aed /lib/ExecutionEngine/ExecutionEngine.cpp
parent2e6baf626d2096eade89e5305bc09e369a761516 (diff)
downloadexternal_llvm-fe854034677f59baca1e38075e71f6efca247a03.zip
external_llvm-fe854034677f59baca1e38075e71f6efca247a03.tar.gz
external_llvm-fe854034677f59baca1e38075e71f6efca247a03.tar.bz2
initial changes to support JIT'ing from multiple module providers, implicitly
linking the program on the fly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@29721 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ExecutionEngine/ExecutionEngine.cpp')
-rw-r--r--lib/ExecutionEngine/ExecutionEngine.cpp206
1 files changed, 150 insertions, 56 deletions
diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp
index 4ea6230..9ad6b57 100644
--- a/lib/ExecutionEngine/ExecutionEngine.cpp
+++ b/lib/ExecutionEngine/ExecutionEngine.cpp
@@ -35,19 +35,33 @@ namespace {
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 @@ static void *CreateArgv(ExecutionEngine *EE,
/// 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 @@ void ExecutionEngine::emitGlobals() {
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