2010-03-01 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / mini-llvm-cpp.cpp
index 6d530e730e9147cbf58e590664a235d8ae7c731b..110cc97f949e984e2a0ef6874bebe57bfeecf4d8 100644 (file)
 
 #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"
@@ -39,6 +43,8 @@
 
 #include "mini-llvm-cpp.h"
 
+extern "C" void LLVMInitializeX86TargetInfo();
+
 using namespace llvm;
 
 class MonoJITMemoryManager : public JITMemoryManager
@@ -63,16 +69,18 @@ public:
     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);
   
@@ -94,6 +102,14 @@ public:
        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 ()
@@ -121,13 +137,15 @@ MonoJITMemoryManager::AllocateGOT()
 {
        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)
@@ -184,8 +202,6 @@ static MonoJITMemoryManager *mono_mm;
 
 static FunctionPassManager *fpm;
 
-static LLVMContext ctx;
-
 void
 mono_llvm_optimize_method (LLVMValueRef method)
 {
@@ -197,7 +213,7 @@ void
 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 */
@@ -206,25 +222,59 @@ mono_llvm_build_alloca (LLVMBuilderRef builder, LLVMTypeRef Ty,
                                                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);
 
@@ -232,14 +282,17 @@ mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, Func
   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));
 
@@ -259,11 +312,7 @@ mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, Func
 
       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);