#include "llvm/GlobalVariable.h"
#include "llvm/Instructions.h"
#include "llvm/ModuleProvider.h"
-#include "llvm/CodeGen/MachineCodeEmitter.h"
-#include "llvm/ExecutionEngine/GenericValue.h"
+#include "llvm/CodeGen/JITCodeEmitter.h"
#include "llvm/CodeGen/MachineCodeInfo.h"
+#include "llvm/ExecutionEngine/GenericValue.h"
+#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetJITInfo.h"
}
-namespace llvm {
- void LinkInJIT() {
- }
+extern "C" void LLVMLinkInJIT() {
}
jitstate = new JITState(MP);
- // Initialize MCE
- MCE = createEmitter(*this, JMM);
+ // Initialize JCE
+ JCE = createEmitter(*this, JMM);
// Add target data
MutexGuard locked(lock);
// Turn the machine code intermediate representation into bytes in memory that
// may be executed.
- if (TM.addPassesToEmitMachineCode(PM, *MCE, OptLevel)) {
+ if (TM.addPassesToEmitMachineCode(PM, *JCE, OptLevel)) {
cerr << "Target does not support machine code emission!\n";
abort();
}
JIT::~JIT() {
delete jitstate;
- delete MCE;
+ delete JCE;
delete &TM;
}
// Turn the machine code intermediate representation into bytes in memory
// that may be executed.
- if (TM.addPassesToEmitMachineCode(PM, *MCE, CodeGenOpt::Default)) {
+ if (TM.addPassesToEmitMachineCode(PM, *JCE, CodeGenOpt::Default)) {
cerr << "Target does not support machine code emission!\n";
abort();
}
// Turn the machine code intermediate representation into bytes in memory
// that may be executed.
- if (TM.addPassesToEmitMachineCode(PM, *MCE, CodeGenOpt::Default)) {
+ if (TM.addPassesToEmitMachineCode(PM, *JCE, CodeGenOpt::Default)) {
cerr << "Target does not support machine code emission!\n";
abort();
}
// Turn the machine code intermediate representation into bytes in memory
// that may be executed.
- if (TM.addPassesToEmitMachineCode(PM, *MCE, CodeGenOpt::Default)) {
+ if (TM.addPassesToEmitMachineCode(PM, *JCE, CodeGenOpt::Default)) {
cerr << "Target does not support machine code emission!\n";
abort();
}
return runFunction(Stub, std::vector<GenericValue>());
}
+void JIT::RegisterJITEventListener(JITEventListener *L) {
+ if (L == NULL)
+ return;
+ MutexGuard locked(lock);
+ EventListeners.push_back(L);
+}
+void JIT::UnregisterJITEventListener(JITEventListener *L) {
+ if (L == NULL)
+ return;
+ MutexGuard locked(lock);
+ std::vector<JITEventListener*>::reverse_iterator I=
+ std::find(EventListeners.rbegin(), EventListeners.rend(), L);
+ if (I != EventListeners.rend()) {
+ std::swap(*I, EventListeners.back());
+ EventListeners.pop_back();
+ }
+}
+void JIT::NotifyFunctionEmitted(
+ const Function &F,
+ void *Code, size_t Size,
+ const JITEvent_EmittedFunctionDetails &Details) {
+ MutexGuard locked(lock);
+ for (unsigned I = 0, S = EventListeners.size(); I < S; ++I) {
+ EventListeners[I]->NotifyFunctionEmitted(F, Code, Size, Details);
+ }
+}
+
+void JIT::NotifyFreeingMachineCode(const Function &F, void *OldPtr) {
+ MutexGuard locked(lock);
+ for (unsigned I = 0, S = EventListeners.size(); I < S; ++I) {
+ EventListeners[I]->NotifyFreeingMachineCode(F, OldPtr);
+ }
+}
+
/// runJITOnFunction - Run the FunctionPassManager full of
/// just-in-time compilation passes on F, hopefully filling in
/// GlobalAddress[F] with the address of F's machine code.
void JIT::runJITOnFunction(Function *F, MachineCodeInfo *MCI) {
MutexGuard locked(lock);
- registerMachineCodeInfo(MCI);
+ class MCIListener : public JITEventListener {
+ MachineCodeInfo *const MCI;
+ public:
+ MCIListener(MachineCodeInfo *mci) : MCI(mci) {}
+ virtual void NotifyFunctionEmitted(const Function &,
+ void *Code, size_t Size,
+ const EmittedFunctionDetails &) {
+ MCI->setAddress(Code);
+ MCI->setSize(Size);
+ }
+ };
+ MCIListener MCIL(MCI);
+ RegisterJITEventListener(&MCIL);
runJITOnFunctionUnlocked(F, locked);
- registerMachineCodeInfo(0);
+ UnregisterJITEventListener(&MCIL);
}
void JIT::runJITOnFunctionUnlocked(Function *F, const MutexGuard &locked) {
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()) {
Ptr = (char*)Ptr + (MisAligned ? (A-MisAligned) : 0);
}
} else {
- Ptr = MCE->allocateSpace(S, A);
+ Ptr = JCE->allocateSpace(S, A);
}
addGlobalMapping(GV, Ptr);
EmitGlobalVariable(GV);
MutexGuard locked(lock);
jitstate->getPendingFunctions(locked).push_back(F);
}
+
+
+JITEventListener::~JITEventListener() {}