#include "llvm/GlobalVariable.h"
#include "llvm/Instructions.h"
#include "llvm/ModuleProvider.h"
-#include "llvm/CodeGen/MachineCodeEmitter.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() {
}
extern "C" void __register_frame(void*);
-#if defined(__APPLE__)
+#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED <= 1050
+# define USE_KEYMGR 1
+#else
+# define USE_KEYMGR 0
+#endif
+
+#if USE_KEYMGR
namespace {
ExecutionEngine *ExecutionEngine::createJIT(ModuleProvider *MP,
std::string *ErrorStr,
JITMemoryManager *JMM,
- bool Fast) {
- ExecutionEngine *EE = JIT::createJIT(MP, ErrorStr, JMM, Fast);
+ CodeGenOpt::Level OptLevel) {
+ ExecutionEngine *EE = JIT::createJIT(MP, ErrorStr, JMM, OptLevel);
if (!EE) return 0;
// Make sure we can resolve symbols in the program as well. The zero arg
}
JIT::JIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji,
- JITMemoryManager *JMM, bool Fast)
+ JITMemoryManager *JMM, CodeGenOpt::Level OptLevel)
: ExecutionEngine(MP), TM(tm), TJI(tji) {
setTargetData(TM.getTargetData());
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, Fast)) {
+ if (TM.addPassesToEmitMachineCode(PM, *JCE, OptLevel)) {
cerr << "Target does not support machine code emission!\n";
abort();
}
// Register routine for informing unwinding runtime about new EH frames
#if defined(__GNUC__) && !defined(__ARM_EABI__)
-#if defined(__APPLE__)
+#if USE_KEYMGR
struct LibgccObjectInfo* LOI = (struct LibgccObjectInfo*)
_keymgr_get_and_lock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST);
// The key is created on demand, and libgcc creates it the first time an
// exception occurs. Since we need the key to register frames, we create
// it now.
- if (!LOI) {
- LOI = (LibgccObjectInfo*)malloc(sizeof(struct LibgccObjectInfo));
- _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST,
- LOI);
- }
+ if (!LOI)
+ LOI = (LibgccObjectInfo*)calloc(sizeof(struct LibgccObjectInfo), 1);
+ _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, LOI);
InstallExceptionTableRegister(DarwinRegisterFrame);
#else
InstallExceptionTableRegister(__register_frame);
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, false /*fast*/)) {
+ 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, false /*fast*/)) {
+ 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, false /*fast*/)) {
+ 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) {
+void JIT::runJITOnFunction(Function *F, MachineCodeInfo *MCI) {
MutexGuard locked(lock);
+
+ 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);
+
+ 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()) {
}
if (F->isDeclaration()) {
- bool AbortOnFailure = F->getLinkage() != GlobalValue::ExternalWeakLinkage;
+ bool AbortOnFailure =
+ !areDlsymStubsEnabled() && !F->hasExternalWeakLinkage();
void *Addr = getPointerToNamedFunction(F->getName(), AbortOnFailure);
addGlobalMapping(F, Addr);
return Addr;
// emit it into memory. It goes in the same array as the generated
// code, jump tables, etc.
const Type *GlobalType = GV->getType()->getElementType();
- size_t S = getTargetData()->getTypePaddedSize(GlobalType);
+ size_t S = getTargetData()->getTypeAllocSize(GlobalType);
size_t A = getTargetData()->getPreferredAlignment(GV);
if (GV->isThreadLocal()) {
MutexGuard locked(lock);
Ptr = (char*)Ptr + (MisAligned ? (A-MisAligned) : 0);
}
} else {
- Ptr = MCE->allocateSpace(S, A);
+ Ptr = JCE->allocateSpace(S, A);
}
addGlobalMapping(GV, Ptr);
EmitGlobalVariable(GV);
///
char* JIT::getMemoryForGV(const GlobalVariable* GV) {
const Type *ElTy = GV->getType()->getElementType();
- size_t GVSize = (size_t)getTargetData()->getTypePaddedSize(ElTy);
+ size_t GVSize = (size_t)getTargetData()->getTypeAllocSize(ElTy);
if (GV->isThreadLocal()) {
MutexGuard locked(lock);
return TJI.allocateThreadLocalMemory(GVSize);
MutexGuard locked(lock);
jitstate->getPendingFunctions(locked).push_back(F);
}
+
+
+JITEventListener::~JITEventListener() {}