#include <stdint.h>
+#include <llvm/Support/raw_ostream.h>
#include <llvm/PassManager.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/JITMemoryManager.h>
+#include <llvm/ExecutionEngine/JITEventListener.h>
#include <llvm/Target/TargetOptions.h>
#include <llvm/Target/TargetData.h>
#include <llvm/Analysis/Verifier.h>
#include <llvm/Transforms/Scalar.h>
#include <llvm/Support/CommandLine.h>
#include "llvm/Support/PassNameParser.h"
+#include "llvm/Support/PrettyStackTrace.h"
#include <llvm/CodeGen/Passes.h>
#include <llvm/CodeGen/MachineFunctionPass.h>
+#include <llvm/CodeGen/MachineFunction.h>
//#include <llvm/LinkAllPasses.h>
#include "llvm-c/Core.h"
#include "mini-llvm-cpp.h"
+extern "C" void LLVMInitializeX86TargetInfo();
+
using namespace llvm;
class MonoJITMemoryManager : public JITMemoryManager
unsigned char *getGOTBase() const {
return mm->getGOTBase ();
}
-
+
+#if LLVM_MAJOR_VERSION == 2 && LLVM_MINOR_VERSION < 7
void *getDlsymTable() const {
return mm->getDlsymTable ();
}
+ void SetDlsymTable(void *ptr);
+#endif
+
void setPoisonMemory(bool) {
}
-
- void SetDlsymTable(void *ptr);
-
+
unsigned char *startFunctionBody(const Function *F,
uintptr_t &ActualSize);
void endExceptionTable(const Function *F, unsigned char *TableStart,
unsigned char *TableEnd,
unsigned char* FrameRegister);
+
+#if LLVM_MAJOR_VERSION == 2 && LLVM_MINOR_VERSION >= 7
+ virtual void deallocateFunctionBody(void*) {
+ }
+
+ virtual void deallocateExceptionTable(void*) {
+ }
+#endif
};
MonoJITMemoryManager::MonoJITMemoryManager ()
{
mm->AllocateGOT ();
}
-
+
+#if LLVM_MAJOR_VERSION == 2 && LLVM_MINOR_VERSION < 7
void
MonoJITMemoryManager::SetDlsymTable(void *ptr)
{
mm->SetDlsymTable (ptr);
}
-
+#endif
+
unsigned char *
MonoJITMemoryManager::startFunctionBody(const Function *F,
uintptr_t &ActualSize)
static FunctionPassManager *fpm;
-static LLVMContext ctx;
-
void
mono_llvm_optimize_method (LLVMValueRef method)
{
mono_llvm_dump_value (LLVMValueRef value)
{
/* Same as LLVMDumpValue (), but print to stdout */
- cout << (*unwrap<Value> (value));
+ outs () << (*unwrap<Value> (value));
}
/* Missing overload for building an alloca with an alignment */
LLVMValueRef ArraySize,
int alignment, const char *Name)
{
- return wrap (unwrap (builder)->Insert (new AllocaInst (ctx, unwrap (Ty), unwrap (ArraySize), alignment), Name));
+ return wrap (unwrap (builder)->Insert (new AllocaInst (unwrap (Ty), unwrap (ArraySize), alignment), Name));
}
LLVMValueRef
-mono_llvm_build_volatile_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
- const char *Name)
+mono_llvm_build_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
+ const char *Name, gboolean is_volatile)
{
- return wrap(unwrap(builder)->CreateLoad(unwrap(PointerVal), true, Name));
+ return wrap(unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name));
+}
+
+void
+mono_llvm_replace_uses_of (LLVMValueRef var, LLVMValueRef v)
+{
+ Value *V = ConstantExpr::getTruncOrBitCast (unwrap<Constant> (v), unwrap (var)->getType ());
+ unwrap (var)->replaceAllUsesWith (V);
}
static cl::list<const PassInfo*, bool, PassNameParser>
PassList(cl::desc("Optimizations available:"));
+class MonoJITEventListener : public JITEventListener {
+ virtual void NotifyFunctionEmitted(const Function &F,
+ void *Code, size_t Size,
+ const EmittedFunctionDetails &Details) {
+ /*
+ * X86TargetMachine::setCodeModelForJIT() sets the code model to Large on amd64,
+ * which means the JIT will generate calls of the form
+ * mov reg, <imm>
+ * call *reg
+ * Our trampoline code can't patch this. Passing CodeModel::Small to createJIT
+ * doesn't seem to work, we need Default. A discussion is here:
+ * http://lists.cs.uiuc.edu/pipermail/llvmdev/2009-December/027999.html
+ * There seems to no way to get the TargeMachine used by an EE either, so we
+ * install a profiler hook and reset the code model here.
+ * This should be inside an ifdef, but we can't include our config.h either,
+ * since its definitions conflict with LLVM's config.h.
+ *
+ */
+ //#if defined(TARGET_X86) || defined(TARGET_AMD64)
+ if (Details.MF->getTarget ().getCodeModel () == CodeModel::Large) {
+ Details.MF->getTarget ().setCodeModel (CodeModel::Default);
+ }
+ //#endif
+ }
+};
+
LLVMExecutionEngineRef
mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb)
{
std::string Error;
LLVMInitializeX86Target ();
+ LLVMInitializeX86TargetInfo ();
llvm::cl::ParseEnvironmentOptions("mono", "MONO_LLVM", "", false);
mono_mm->alloc_cb = alloc_cb;
mono_mm->emitted_cb = emitted_cb;
- ExceptionHandling = true;
+ DwarfExceptionHandling = true;
+ // PrettyStackTrace installs signal handlers which trip up libgc
+ DisablePrettyStackTrace = true;
ExecutionEngine *EE = ExecutionEngine::createJIT (unwrap (MP), &Error, mono_mm, CodeGenOpt::Default);
if (!EE) {
- cerr << "Unable to create LLVM ExecutionEngine: " << Error << "\n";
+ errs () << "Unable to create LLVM ExecutionEngine: " << Error << "\n";
g_assert_not_reached ();
}
EE->InstallExceptionTableRegister (exception_cb);
+ EE->RegisterJITEventListener (new MonoJITEventListener ());
fpm = new FunctionPassManager (unwrap (MP));
if (PassInf->getNormalCtor())
P = PassInf->getNormalCtor()();
- if (dynamic_cast<MachineFunctionPass*>(P) != 0) {
- cerr << PassInf->getPassName () << " is a machine function pass.\n";
- } else {
- fpm->add (P);
- }
+ fpm->add (P);
}
return wrap(EE);