2009-07-01 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / mini-llvm-cpp.cpp
index 9c04d1dbc01dfd0eb9c8826e5567c4e327500fe3..f379b20c666ebc941d17288a7778be674561db2d 100644 (file)
@@ -10,6 +10,8 @@
 // The things which we override are:
 // - the default JIT code manager used by LLVM doesn't allocate memory using
 //   MAP_32BIT, we require it.
+// - add some callbacks so we can obtain the size of methods and their exception
+//   tables.
 //
 
 //
 
 #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/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/LinkAllPasses.h>
 
 #include "llvm-c/Core.h"
 #include "llvm-c/ExecutionEngine.h"
 
-using namespace llvm;
+#include "mini-llvm-cpp.h"
+
+extern "C" void LLVMInitializeX86TargetInfo();
 
-typedef unsigned char * (AllocCodeMemoryCb) (LLVMValueRef function, int size);
-typedef void (FunctionEmittedCb) (LLVMValueRef function, void *start, void *end);
-typedef void (ExceptionTableCb) (void *data);
+using namespace llvm;
 
 class MonoJITMemoryManager : public JITMemoryManager
 {
@@ -58,6 +71,9 @@ public:
     void *getDlsymTable() const {
                return mm->getDlsymTable ();
     }
+
+       void setPoisonMemory(bool) {
+       }
       
        void SetDlsymTable(void *ptr);
   
@@ -71,6 +87,8 @@ public:
                                                 unsigned char *FunctionEnd);
 
        unsigned char *allocateSpace(intptr_t Size, unsigned Alignment);
+
+       uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment);
   
        void deallocateMemForFunction(const Function *F);
   
@@ -140,7 +158,13 @@ MonoJITMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment)
 {
        return new unsigned char [Size];
 }
-  
+
+uint8_t *
+MonoJITMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment)
+{
+       return new unsigned char [Size];
+}
+
 void
 MonoJITMemoryManager::deallocateMemForFunction(const Function *F)
 {
@@ -162,23 +186,100 @@ MonoJITMemoryManager::endExceptionTable(const Function *F, unsigned char *TableS
 
 static MonoJITMemoryManager *mono_mm;
 
-extern "C" {
+static FunctionPassManager *fpm;
+
+static LLVMContext ctx;
+
+void
+mono_llvm_optimize_method (LLVMValueRef method)
+{
+       verifyFunction (*(unwrap<Function> (method)));
+       fpm->run (*unwrap<Function> (method));
+}
+
+void
+mono_llvm_dump_value (LLVMValueRef value)
+{
+       /* Same as LLVMDumpValue (), but print to stdout */
+       outs () << (*unwrap<Value> (value));
+}
+
+/* Missing overload for building an alloca with an alignment */
+LLVMValueRef
+mono_llvm_build_alloca (LLVMBuilderRef builder, LLVMTypeRef Ty, 
+                                               LLVMValueRef ArraySize,
+                                               int alignment, const char *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)
+{
+       return wrap(unwrap(builder)->CreateLoad(unwrap(PointerVal), true, Name));
+}
+
+static cl::list<const PassInfo*, bool, PassNameParser>
+PassList(cl::desc("Optimizations available:"));
 
 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 = new MonoJITMemoryManager ();
   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, false);
+  ExecutionEngine *EE = ExecutionEngine::createJIT (unwrap (MP), &Error, mono_mm, CodeGenOpt::Default);
+  if (!EE) {
+         errs () << "Unable to create LLVM ExecutionEngine: " << Error << "\n";
+         g_assert_not_reached ();
+  }
   EE->InstallExceptionTableRegister (exception_cb);
 
+  fpm = new FunctionPassManager (unwrap (MP));
+
+  fpm->add(new TargetData(*EE->getTargetData()));
+  /* Add a random set of passes */
+  /* Make this run-time configurable */
+  fpm->add(createInstructionCombiningPass());
+  fpm->add(createReassociatePass());
+  fpm->add(createGVNPass());
+  fpm->add(createCFGSimplificationPass());
+
+  /* Add passes specified by the env variable */
+  /* FIXME: This can only add passes which are linked in, thus are already used */
+  for (unsigned i = 0; i < PassList.size(); ++i) {
+      const PassInfo *PassInf = PassList[i];
+      Pass *P = 0;
+
+      if (PassInf->getNormalCtor())
+                 P = PassInf->getNormalCtor()();
+         if (dynamic_cast<MachineFunctionPass*>(P) != 0) {
+                 errs () << PassInf->getPassName () << " is a machine function pass.\n";
+         } else {
+                 fpm->add (P);
+         }
+  }
+
   return wrap(EE);
 }
 
+void
+mono_llvm_dispose_ee (LLVMExecutionEngineRef ee)
+{
+       delete unwrap (ee);
+
+       delete fpm;
 }