#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MutexGuard.h"
-#include "llvm/System/DynamicLibrary.h"
+#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Config/config.h"
using namespace llvm;
-#ifdef __APPLE__
+#ifdef __APPLE__
// Apple gcc defaults to -fuse-cxa-atexit (i.e. calls __cxa_atexit instead
// of atexit). It passes the address of linker generated symbol __dso_handle
// to the function.
extern "C" void LLVMLinkInJIT() {
}
+// Determine whether we can register EH tables.
+#if (defined(__GNUC__) && !defined(__ARM_EABI__) && \
+ !defined(__USING_SJLJ_EXCEPTIONS__))
+#define HAVE_EHTABLE_SUPPORT 1
+#else
+#define HAVE_EHTABLE_SUPPORT 0
+#endif
+
+#if HAVE_EHTABLE_SUPPORT
-#if defined(__GNUC__) && !defined(__ARM__EABI__)
-
// libgcc defines the __register_frame function to dynamically register new
// dwarf frames for exception handling. This functionality is not portable
// across compilers and is only provided by GCC. We use the __register_frame
// values of an opaque key, used by libgcc to find dwarf tables.
extern "C" void __register_frame(void*);
+extern "C" void __deregister_frame(void*);
#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED <= 1050
# define USE_KEYMGR 1
void *unused1;
void *unused2;
void *unused3;
-
+
/// frame - Pointer to the exception table.
void *frame;
-
+
/// encoding - The encoding of the object?
union {
struct {
unsigned long from_array : 1;
unsigned long mixed_encoding : 1;
unsigned long encoding : 8;
- unsigned long count : 21;
+ unsigned long count : 21;
} b;
size_t i;
} encoding;
-
+
/// fde_end - libgcc defines this field only if some macro is defined. We
/// include this field even if it may not there, to make libgcc happy.
char *fde_end;
-
+
/// next - At least we know it's a chained list!
struct LibgccObject *next;
};
/// unseenObjects - LibgccObjects not parsed yet by the unwinding runtime.
///
struct LibgccObject* unseenObjects;
-
+
unsigned unused[2];
};
LibgccObjectInfo* LOI = (struct LibgccObjectInfo*)
_keymgr_get_and_lock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST);
assert(LOI && "This should be preallocated by the runtime");
-
+
// Allocate a new LibgccObject to represent this frame. Deallocation of this
// object may be impossible: since darwin code in libgcc was written after
// the ability to dynamically register frames, things may crash if we
// deallocate it.
struct LibgccObject* ob = (struct LibgccObject*)
malloc(sizeof(struct LibgccObject));
-
+
// Do like libgcc for the values of the field.
ob->unused1 = (void *)-1;
ob->unused2 = 0;
ob->unused3 = 0;
ob->frame = FrameBegin;
- ob->encoding.i = 0;
+ ob->encoding.i = 0;
ob->encoding.b.encoding = llvm::dwarf::DW_EH_PE_omit;
-
+
// Put the info on both places, as libgcc uses the first or the second
// field. Note that we rely on having two pointers here. If fde_end was a
// char, things would get complicated.
ob->fde_end = (char*)LOI->unseenObjects;
ob->next = LOI->unseenObjects;
-
+
// Update the key's unseenObjects list.
LOI->unseenObjects = ob;
-
- // Finally update the "key". Apparently, libgcc requires it.
+
+ // Finally update the "key". Apparently, libgcc requires it.
_keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST,
LOI);
}
#endif // __APPLE__
-#endif // __GNUC__
+#endif // HAVE_EHTABLE_SUPPORT
/// createJIT - This is the factory method for creating a JIT for the current
/// machine, it does not fall back to the interpreter. This takes ownership
/// of the module.
-ExecutionEngine *ExecutionEngine::createJIT(Module *M,
- std::string *ErrorStr,
- JITMemoryManager *JMM,
- CodeGenOpt::Level OptLevel,
- bool GVsWithCode,
- CodeModel::Model CMM) {
- // Use the defaults for extra parameters. Users can use EngineBuilder to
- // set them.
- StringRef MArch = "";
- StringRef MCPU = "";
- SmallVector<std::string, 1> MAttrs;
- return JIT::createJIT(M, ErrorStr, JMM, OptLevel, GVsWithCode, CMM,
- MArch, MCPU, MAttrs);
-}
-
ExecutionEngine *JIT::createJIT(Module *M,
std::string *ErrorStr,
JITMemoryManager *JMM,
CodeGenOpt::Level OptLevel,
bool GVsWithCode,
- CodeModel::Model CMM,
- StringRef MArch,
- StringRef MCPU,
- const SmallVectorImpl<std::string>& MAttrs) {
- // Make sure we can resolve symbols in the program as well. The zero arg
- // to the function tells DynamicLibrary to load the program, not a library.
- if (sys::DynamicLibrary::LoadLibraryPermanently(0, ErrorStr))
- return 0;
+ TargetMachine *TM) {
+ // Try to register the program as a source of symbols to resolve against.
+ //
+ // FIXME: Don't do this here.
+ sys::DynamicLibrary::LoadLibraryPermanently(0, NULL);
- // Pick a target either via -march or by guessing the native arch.
- TargetMachine *TM = JIT::selectTarget(M, MArch, MCPU, MAttrs, ErrorStr);
- if (!TM || (ErrorStr && ErrorStr->length() > 0)) return 0;
- TM->setCodeModel(CMM);
-
- // If the target supports JIT code generation, create a the JIT.
+ // If the target supports JIT code generation, create the JIT.
if (TargetJITInfo *TJ = TM->getJITInfo()) {
return new JIT(M, *TM, *TJ, JMM, OptLevel, GVsWithCode);
} else {
// Turn the machine code intermediate representation into bytes in memory that
// may be executed.
if (TM.addPassesToEmitMachineCode(PM, *JCE, OptLevel)) {
- llvm_report_error("Target does not support machine code emission!");
+ report_fatal_error("Target does not support machine code emission!");
}
-
+
// Register routine for informing unwinding runtime about new EH frames
-#if defined(__GNUC__) && !defined(__ARM_EABI__)
+#if HAVE_EHTABLE_SUPPORT
#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*)calloc(sizeof(struct LibgccObjectInfo), 1);
+ LOI = (LibgccObjectInfo*)calloc(sizeof(struct LibgccObjectInfo), 1);
_keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, LOI);
InstallExceptionTableRegister(DarwinRegisterFrame);
+ // Not sure about how to deregister on Darwin.
#else
InstallExceptionTableRegister(__register_frame);
+ InstallExceptionTableDeregister(__deregister_frame);
#endif // __APPLE__
-#endif // __GNUC__
-
+#endif // HAVE_EHTABLE_SUPPORT
+
// Initialize passes.
PM.doInitialization();
}
JIT::~JIT() {
+ // Unregister all exception tables registered by this JIT.
+ DeregisterAllTables();
+ // Cleanup.
AllJits->Remove(this);
delete jitstate;
delete JCE;
// Turn the machine code intermediate representation into bytes in memory
// that may be executed.
if (TM.addPassesToEmitMachineCode(PM, *JCE, CodeGenOpt::Default)) {
- llvm_report_error("Target does not support machine code emission!");
+ report_fatal_error("Target does not support machine code emission!");
}
-
+
// Initialize passes.
PM.doInitialization();
}
-
+
ExecutionEngine::addModule(M);
}
/// since the PassManager it contains references a released Module.
bool JIT::removeModule(Module *M) {
bool result = ExecutionEngine::removeModule(M);
-
+
MutexGuard locked(lock);
-
+
if (jitstate->getModule() == M) {
delete jitstate;
jitstate = 0;
}
-
+
if (!jitstate && !Modules.empty()) {
jitstate = new JITState(Modules[0]);
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, *JCE, CodeGenOpt::Default)) {
- llvm_report_error("Target does not support machine code emission!");
+ report_fatal_error("Target does not support machine code emission!");
}
-
+
// Initialize passes.
PM.doInitialization();
- }
+ }
return result;
}
// Handle some common cases first. These cases correspond to common `main'
// prototypes.
- if (RetTy->isInteger(32) || RetTy->isVoidTy()) {
+ if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) {
switch (ArgValues.size()) {
case 3:
- if (FTy->getParamType(0)->isInteger(32) &&
- isa<PointerType>(FTy->getParamType(1)) &&
- isa<PointerType>(FTy->getParamType(2))) {
+ if (FTy->getParamType(0)->isIntegerTy(32) &&
+ FTy->getParamType(1)->isPointerTy() &&
+ FTy->getParamType(2)->isPointerTy()) {
int (*PF)(int, char **, const char **) =
(int(*)(int, char **, const char **))(intptr_t)FPtr;
// Call the function.
GenericValue rv;
- rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
+ rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
(char **)GVTOP(ArgValues[1]),
(const char **)GVTOP(ArgValues[2])));
return rv;
}
break;
case 2:
- if (FTy->getParamType(0)->isInteger(32) &&
- isa<PointerType>(FTy->getParamType(1))) {
+ if (FTy->getParamType(0)->isIntegerTy(32) &&
+ FTy->getParamType(1)->isPointerTy()) {
int (*PF)(int, char **) = (int(*)(int, char **))(intptr_t)FPtr;
// Call the function.
GenericValue rv;
- rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
+ rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
(char **)GVTOP(ArgValues[1])));
return rv;
}
break;
case 1:
if (FTy->getNumParams() == 1 &&
- FTy->getParamType(0)->isInteger(32)) {
+ FTy->getParamType(0)->isIntegerTy(32)) {
GenericValue rv;
int (*PF)(int) = (int(*)(int))(intptr_t)FPtr;
rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue()));
rv.IntVal = APInt(BitWidth, ((int(*)())(intptr_t)FPtr)());
else if (BitWidth <= 64)
rv.IntVal = APInt(BitWidth, ((int64_t(*)())(intptr_t)FPtr)());
- else
+ else
llvm_unreachable("Integer types > 64 bits not supported");
return rv;
}
case Type::PointerTyID:
void *ArgPtr = GVTOP(AV);
if (sizeof(void*) == 4)
- C = ConstantInt::get(Type::getInt32Ty(F->getContext()),
+ C = ConstantInt::get(Type::getInt32Ty(F->getContext()),
(int)(intptr_t)ArgPtr);
else
C = ConstantInt::get(Type::getInt64Ty(F->getContext()),
void JIT::runJITOnFunctionUnlocked(Function *F, const MutexGuard &locked) {
assert(!isAlreadyCodeGenerating && "Error: Recursive compilation detected!");
- // JIT the function
- isAlreadyCodeGenerating = true;
- jitstate->getPM(locked).run(*F);
- isAlreadyCodeGenerating = false;
+ jitTheFunction(F, locked);
// If the function referred to another function that had not yet been
// read from bitcode, and we are jitting non-lazily, emit it now.
assert(!PF->hasAvailableExternallyLinkage() &&
"Externally-defined function should not be in pending list.");
- // JIT the function
- isAlreadyCodeGenerating = true;
- jitstate->getPM(locked).run(*PF);
- isAlreadyCodeGenerating = false;
-
+ jitTheFunction(PF, locked);
+
// Now that the function has been jitted, ask the JITEmitter to rewrite
// the stub with real address of the function.
updateFunctionStub(PF);
}
}
+void JIT::jitTheFunction(Function *F, const MutexGuard &locked) {
+ isAlreadyCodeGenerating = true;
+ jitstate->getPM(locked).run(*F);
+ isAlreadyCodeGenerating = false;
+
+ // clear basic block addresses after this function is done
+ getBasicBlockAddressMap(locked).clear();
+}
+
/// getPointerToFunction - This method is used to get the address of the
-/// specified function, compiling it if neccesary.
+/// specified function, compiling it if necessary.
///
void *JIT::getPointerToFunction(Function *F) {
// exists in this Module.
std::string ErrorMsg;
if (F->Materialize(&ErrorMsg)) {
- llvm_report_error("Error reading function '" + F->getName()+
+ report_fatal_error("Error reading function '" + F->getName()+
"' from bitcode file: " + ErrorMsg);
}
return Addr;
}
+void JIT::addPointerToBasicBlock(const BasicBlock *BB, void *Addr) {
+ MutexGuard locked(lock);
+
+ BasicBlockAddressMapTy::iterator I =
+ getBasicBlockAddressMap(locked).find(BB);
+ if (I == getBasicBlockAddressMap(locked).end()) {
+ getBasicBlockAddressMap(locked)[BB] = Addr;
+ } else {
+ // ignore repeats: some BBs can be split into few MBBs?
+ }
+}
+
+void JIT::clearPointerToBasicBlock(const BasicBlock *BB) {
+ MutexGuard locked(lock);
+ getBasicBlockAddressMap(locked).erase(BB);
+}
+
+void *JIT::getPointerToBasicBlock(BasicBlock *BB) {
+ // make sure it's function is compiled by JIT
+ (void)getPointerToFunction(BB->getParent());
+
+ // resolve basic block address
+ MutexGuard locked(lock);
+
+ BasicBlockAddressMapTy::iterator I =
+ getBasicBlockAddressMap(locked).find(BB);
+ if (I != getBasicBlockAddressMap(locked).end()) {
+ return I->second;
+ } else {
+ assert(0 && "JIT does not have BB address for address-of-label, was"
+ " it eliminated by optimizer?");
+ return 0;
+ }
+}
+
/// getOrEmitGlobalVariable - Return the address of the specified global
/// variable, possibly emitting it to memory if needed. This is used by the
/// Emitter.
#endif
Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(GV->getName());
if (Ptr == 0) {
- llvm_report_error("Could not resolve external global address: "
+ report_fatal_error("Could not resolve external global address: "
+GV->getName());
}
addGlobalMapping(GV, Ptr);
// situation. It's returned in the same block of memory as code which may
// not be writable.
if (isGVCompilationDisabled() && !GV->isConstant()) {
- llvm_report_error("Compilation of non-internal GlobalValue is disabled!");
+ report_fatal_error("Compilation of non-internal GlobalValue is disabled!");
}
// Some applications require globals and code to live together, so they may