JIT::JIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji,
JITMemoryManager *JMM)
- : ExecutionEngine(MP), TM(tm), TJI(tji), jitstate(MP) {
+ : ExecutionEngine(MP), TM(tm), TJI(tji) {
setTargetData(TM.getTargetData());
+ jitstate = new JITState(MP);
+
// Initialize MCE
MCE = createEmitter(*this, JMM);
// Add target data
MutexGuard locked(lock);
- FunctionPassManager &PM = jitstate.getPM(locked);
+ FunctionPassManager &PM = jitstate->getPM(locked);
PM.add(new TargetData(*TM.getTargetData()));
// Turn the machine code intermediate representation into bytes in memory that
}
JIT::~JIT() {
+ delete jitstate;
delete MCE;
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) {
+ MutexGuard locked(lock);
+
+ if (Modules.empty()) {
+ assert(!jitstate && "jitstate should be NULL if Modules vector is empty!");
+
+ jitstate = new JITState(MP);
+
+ 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, *MCE, false /*fast*/)) {
+ cerr << "Target does not support machine code emission!\n";
+ abort();
+ }
+
+ // Initialize passes.
+ PM.doInitialization();
+ }
+
+ ExecutionEngine::addModuleProvider(MP);
+}
+
+/// 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);
+
+ MutexGuard locked(lock);
+ if (Modules.empty()) {
+ delete jitstate;
+ jitstate = 0;
+ }
+
+ return result;
+}
+
/// run - Start execution with the specified function and arguments.
///
GenericValue JIT::runFunction(Function *F,
Args.push_back(C);
}
- CallInst *TheCall = CallInst::Create(F, Args.begin(), Args.end(), "", StubBB);
+ CallInst *TheCall = CallInst::Create(F, Args.begin(), Args.end(),
+ "", StubBB);
TheCall->setTailCall();
if (TheCall->getType() != Type::VoidTy)
- ReturnInst::Create(TheCall, StubBB); // Return result of the call.
+ ReturnInst::Create(TheCall, StubBB); // Return result of the call.
else
- ReturnInst::Create(StubBB); // Just return void.
+ ReturnInst::Create(StubBB); // Just return void.
// Finally, return the value returned by our nullary stub function.
return runFunction(Stub, std::vector<GenericValue>());
// JIT the function
isAlreadyCodeGenerating = true;
- jitstate.getPM(locked).run(*F);
+ jitstate->getPM(locked).run(*F);
isAlreadyCodeGenerating = false;
// If the function referred to a global variable that had not yet been
// emitted, it allocates memory for the global, but doesn't emit it yet. Emit
// all of these globals now.
- while (!jitstate.getPendingGlobals(locked).empty()) {
- const GlobalVariable *GV = jitstate.getPendingGlobals(locked).back();
- jitstate.getPendingGlobals(locked).pop_back();
+ while (!jitstate->getPendingGlobals(locked).empty()) {
+ const GlobalVariable *GV = jitstate->getPendingGlobals(locked).back();
+ jitstate->getPendingGlobals(locked).pop_back();
EmitGlobalVariable(GV);
}
}
unsigned MisAligned = ((intptr_t)Ptr & (A-1));
Ptr = (char*)Ptr + (MisAligned ? (A-MisAligned) : 0);
}
- jitstate.getPendingGlobals(locked).push_back(GV);
+ jitstate->getPendingGlobals(locked).push_back(GV);
}
addGlobalMapping(GV, Ptr);
return Ptr;