Merge pull request #1109 from adbre/iss358
[mono.git] / mono / mini / mini-llvm-cpp.cpp
index 957e5f5e4f4b63602a5446158b5021f130776234..1f4775368c90fd71af4a0090a8327ef6a09f07e9 100644 (file)
 // possible
 //
 
+#include "config.h"
+//undef those as llvm defines them on its own config.h as well.
+#undef PACKAGE_BUGREPORT
+#undef PACKAGE_NAME
+#undef PACKAGE_STRING
+#undef PACKAGE_TARNAME
+#undef PACKAGE_VERSION
+
 #include <stdint.h>
 
 #include <llvm/Support/raw_ostream.h>
+#include <llvm/Support/Host.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/Target/TargetRegisterInfo.h>
+#if LLVM_API_VERSION >= 1
+#include <llvm/IR/Verifier.h>
+#else
 #include <llvm/Analysis/Verifier.h>
+#endif
 #include <llvm/Analysis/Passes.h>
 #include <llvm/Transforms/Scalar.h>
 #include <llvm/Support/CommandLine.h>
+#if LLVM_API_VERSION >= 1
+#include "llvm/IR/LegacyPassNameParser.h"
+#else
 #include "llvm/Support/PassNameParser.h"
+#endif
 #include "llvm/Support/PrettyStackTrace.h"
 #include <llvm/CodeGen/Passes.h>
 #include <llvm/CodeGen/MachineFunctionPass.h>
 #include <llvm/CodeGen/MachineFunction.h>
 #include <llvm/CodeGen/MachineFrameInfo.h>
+#include <llvm/IR/Function.h>
+#include <llvm/IR/IRBuilder.h>
+#include <llvm/IR/Module.h>
 //#include <llvm/LinkAllPasses.h>
 
 #include "llvm-c/Core.h"
        ((LLVM_MAJOR_VERSION > (major)) ||                                                                      \
         ((LLVM_MAJOR_VERSION == (major)) && (LLVM_MINOR_VERSION >= (minor))))
 
+// extern "C" void LLVMInitializeARMTargetInfo();
+// extern "C" void LLVMInitializeARMTarget ();
+// extern "C" void LLVMInitializeARMTargetMC ();
+
 using namespace llvm;
 
+#ifndef MONO_CROSS_COMPILE
+
 class MonoJITMemoryManager : public JITMemoryManager
 {
 private:
@@ -61,6 +86,7 @@ private:
 public:
        /* Callbacks installed by mono */
        AllocCodeMemoryCb *alloc_cb;
+       DlSymCb *dlsym_cb;
 
        MonoJITMemoryManager ();
        ~MonoJITMemoryManager ();
@@ -106,19 +132,44 @@ public:
        virtual void deallocateExceptionTable(void*) {
        }
 
-       virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
-                                                                                unsigned SectionID) {
+       virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID,
+                                                                                StringRef SectionName) {
                // FIXME:
                assert(0);
                return NULL;
        }
 
-       virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
-                                                                                unsigned SectionID) {
+       virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID,
+                                                                                StringRef SectionName, bool IsReadOnly) {
                // FIXME:
                assert(0);
                return NULL;
        }
+
+       virtual bool applyPermissions(std::string*) {
+               // FIXME:
+               assert(0);
+               return false;
+       }
+
+       virtual bool finalizeMemory(std::string *ErrMsg = 0) {
+               // FIXME:
+               assert(0);
+               return false;
+       }
+
+       virtual void* getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure) {
+               void *res;
+               char *err;
+
+               err = dlsym_cb (Name.c_str (), &res);
+               if (err) {
+                       outs () << "Unable to resolve: " << Name << ": " << err << "\n";
+                       assert(0);
+                       return NULL;
+               }
+               return res;
+       }
 };
 
 MonoJITMemoryManager::MonoJITMemoryManager ()
@@ -201,6 +252,13 @@ MonoJITMemoryManager::endExceptionTable(const Function *F, unsigned char *TableS
 {
 }
 
+#else
+
+class MonoJITMemoryManager {
+};
+
+#endif /* !MONO_CROSS_COMPILE */
+
 class MonoJITEventListener : public JITEventListener {
 
 public:
@@ -225,31 +283,30 @@ public:
                 * 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.
-                *
+                * The LLVM mono branch contains a workaround.
                 */
-               //#if defined(TARGET_X86) || defined(TARGET_AMD64)
-#ifndef LLVM_MONO_BRANCH
-               /* The LLVM mono branch contains a workaround, so this is not needed */
-               if (Details.MF->getTarget ().getCodeModel () == CodeModel::Large) {
-                       Details.MF->getTarget ().setCodeModel (CodeModel::Default);
-               }
-#endif
-               //#endif
-
                emitted_cb (wrap (&F), Code, (char*)Code + Size);
        }
 };
 
-static MonoJITMemoryManager *mono_mm;
-static MonoJITEventListener *mono_event_listener;
-
-static FunctionPassManager *fpm;
+class MonoEE {
+public:
+       ExecutionEngine *EE;
+       MonoJITMemoryManager *mm;
+       MonoJITEventListener *listener;
+       FunctionPassManager *fpm;
+};
 
 void
-mono_llvm_optimize_method (LLVMValueRef method)
+mono_llvm_optimize_method (MonoEERef eeref, LLVMValueRef method)
 {
-       verifyFunction (*(unwrap<Function> (method)));
-       fpm->run (*unwrap<Function> (method));
+       MonoEE *mono_ee = (MonoEE*)eeref;
+
+       /*
+        * The verifier does some checks on the whole module, leading to quadratic behavior.
+        */
+       //verifyFunction (*(unwrap<Function> (method)));
+       mono_ee->fpm->run (*unwrap<Function> (method));
 }
 
 void
@@ -312,7 +369,11 @@ mono_llvm_build_cmpxchg (LLVMBuilderRef builder, LLVMValueRef ptr, LLVMValueRef
 {
        AtomicCmpXchgInst *ins;
 
+#if LLVM_API_VERSION >= 1
+       ins = unwrap(builder)->CreateAtomicCmpXchg (unwrap(ptr), unwrap (cmp), unwrap (val), SequentiallyConsistent, SequentiallyConsistent);
+#else
        ins = unwrap(builder)->CreateAtomicCmpXchg (unwrap(ptr), unwrap (cmp), unwrap (val), SequentiallyConsistent);
+#endif
        return wrap (ins);
 }
 
@@ -361,7 +422,7 @@ static void
 force_pass_linking (void)
 {
        // Make sure the rest is linked in, but never executed
-       if (getenv ("FOO") != (char*)-1)
+       if (g_getenv ("FOO") != (char*)-1)
                return;
 
        // This is a subset of the passes in LinkAllPasses.h
@@ -378,7 +439,7 @@ force_pass_linking (void)
       (void) llvm::createBasicAliasAnalysisPass();
       (void) llvm::createLibCallAliasAnalysisPass(0);
       (void) llvm::createScalarEvolutionAliasAnalysisPass();
-      (void) llvm::createBlockPlacementPass();
+      //(void) llvm::createBlockPlacementPass();
       (void) llvm::createBreakCriticalEdgesPass();
       (void) llvm::createCFGSimplificationPass();
          /*
@@ -415,7 +476,7 @@ force_pass_linking (void)
       (void) llvm::createLCSSAPass();
       (void) llvm::createLICMPass();
       (void) llvm::createLazyValueInfoPass();
-      (void) llvm::createLoopDependenceAnalysisPass();
+      //(void) llvm::createLoopDependenceAnalysisPass();
          /*
       (void) llvm::createLoopExtractorPass();
          */
@@ -448,7 +509,7 @@ force_pass_linking (void)
       (void) llvm::createReassociatePass();
       (void) llvm::createSCCPPass();
       (void) llvm::createScalarReplAggregatesPass();
-      (void) llvm::createSimplifyLibCallsPass();
+      //(void) llvm::createSimplifyLibCallsPass();
          /*
       (void) llvm::createSingleLoopExtractorPass();
       (void) llvm::createStripSymbolsPass();
@@ -485,23 +546,56 @@ force_pass_linking (void)
       (void) llvm::createSinkingPass();
 }
 
-LLVMExecutionEngineRef
-mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb)
+#ifndef MONO_CROSS_COMPILE
+
+static gboolean inited;
+
+static void
+init_llvm (void)
 {
-  std::string Error;
+       if (inited)
+               return;
 
   force_pass_linking ();
 
+#ifdef TARGET_ARM
+  LLVMInitializeARMTarget ();
+  LLVMInitializeARMTargetInfo ();
+  LLVMInitializeARMTargetMC ();
+#else
   LLVMInitializeX86Target ();
   LLVMInitializeX86TargetInfo ();
   LLVMInitializeX86TargetMC ();
+#endif
 
-  mono_mm = new MonoJITMemoryManager ();
-  mono_mm->alloc_cb = alloc_cb;
+  PassRegistry &Registry = *PassRegistry::getPassRegistry();
+  initializeCore(Registry);
+  initializeScalarOpts(Registry);
+  initializeAnalysis(Registry);
+  initializeIPA(Registry);
+  initializeTransformUtils(Registry);
+  initializeInstCombine(Registry);
+  initializeTarget(Registry);
+
+  llvm::cl::ParseEnvironmentOptions("mono", "MONO_LLVM", "");
+
+  inited = true;
+}
+
+MonoEERef
+mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb, LLVMExecutionEngineRef *ee)
+{
+  std::string Error;
+  MonoEE *mono_ee;
+
+  init_llvm ();
 
-  //JITExceptionHandling = true;
-  // PrettyStackTrace installs signal handlers which trip up libgc
-  DisablePrettyStackTrace = true;
+  mono_ee = new MonoEE ();
+
+  MonoJITMemoryManager *mono_mm = new MonoJITMemoryManager ();
+  mono_mm->alloc_cb = alloc_cb;
+  mono_mm->dlsym_cb = dlsym_cb;
+  mono_ee->mm = mono_mm;
 
   /*
    * The Default code model doesn't seem to work on amd64,
@@ -513,41 +607,33 @@ mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, Func
   opts.JITExceptionHandling = 1;
 
   EngineBuilder b (unwrap (MP));
+  EngineBuilder &eb = b;
+  eb = eb.setJITMemoryManager (mono_mm).setTargetOptions (opts).setAllocateGVsWithCode (true);
+#if LLVM_API_VERSION >= 1
+  StringRef cpu_name = sys::getHostCPUName ();
+  eb = eb.setMCPU (cpu_name);
+#endif
 #ifdef TARGET_AMD64
-  ExecutionEngine *EE = b.setJITMemoryManager (mono_mm).setTargetOptions (opts).setCodeModel (CodeModel::Large).setAllocateGVsWithCode (true).create ();
-#else
-  ExecutionEngine *EE = b.setJITMemoryManager (mono_mm).setTargetOptions (opts).setAllocateGVsWithCode (true).create ();
+  eb = eb.setCodeModel (CodeModel::Large);
 #endif
-  g_assert (EE);
 
-#if 0
-  ExecutionEngine *EE = ExecutionEngine::createJIT (unwrap (MP), &Error, mono_mm, CodeGenOpt::Default, true, Reloc::Default, CodeModel::Large);
-  if (!EE) {
-         errs () << "Unable to create LLVM ExecutionEngine: " << Error << "\n";
-         g_assert_not_reached ();
-  }
-#endif
+  ExecutionEngine *EE = eb.create ();
+  g_assert (EE);
+  mono_ee->EE = EE;
 
   EE->InstallExceptionTableRegister (exception_cb);
-  mono_event_listener = new MonoJITEventListener (emitted_cb);
-  EE->RegisterJITEventListener (mono_event_listener);
-
-  fpm = new FunctionPassManager (unwrap (MP));
+  MonoJITEventListener *listener = new MonoJITEventListener (emitted_cb);
+  EE->RegisterJITEventListener (listener);
+  mono_ee->listener = listener;
 
-  fpm->add(new TargetData(*EE->getTargetData()));
+  FunctionPassManager *fpm = new FunctionPassManager (unwrap (MP));
+  mono_ee->fpm = fpm;
 
-  PassRegistry &Registry = *PassRegistry::getPassRegistry();
-  initializeCore(Registry);
-  initializeScalarOpts(Registry);
-  //initializeIPO(Registry);
-  initializeAnalysis(Registry);
-  initializeIPA(Registry);
-  initializeTransformUtils(Registry);
-  initializeInstCombine(Registry);
-  //initializeInstrumentation(Registry);
-  initializeTarget(Registry);
-
-  llvm::cl::ParseEnvironmentOptions("mono", "MONO_LLVM", "", false);
+#if LLVM_API_VERSION >= 1
+  fpm->add(new DataLayoutPass(*EE->getDataLayout()));
+#else
+  fpm->add(new DataLayout(*EE->getDataLayout()));
+#endif
 
   if (PassList.size() > 0) {
          /* Use the passes specified by the env variable */
@@ -562,14 +648,14 @@ mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, Func
          }
   } else {
          /* Use the same passes used by 'opt' by default, without the ipo passes */
-         const char *opts = "-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -basiccg -domtree -domfrontier -scalarrepl -simplify-libcalls -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -domfrontier -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -iv-users -indvars -loop-deletion -loop-simplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -gvn -simplifycfg -preverify -domtree -verify";
+         const char *opts = "-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -domfrontier -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -iv-users -indvars -loop-deletion -loop-simplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -gvn -simplifycfg";
          char **args;
          int i;
 
          args = g_strsplit (opts, " ", 1000);
          for (i = 0; args [i]; i++)
                  ;
-         llvm::cl::ParseCommandLineOptions (i, args, "", false);
+         llvm::cl::ParseCommandLineOptions (i, args, "");
          g_strfreev (args);
 
          for (unsigned i = 0; i < PassList.size(); ++i) {
@@ -578,6 +664,7 @@ mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, Func
 
                  if (PassInf->getNormalCtor())
                          P = PassInf->getNormalCtor()();
+                 g_assert (P->getPassKind () == llvm::PT_Function || P->getPassKind () == llvm::PT_Loop);
                  fpm->add (P);
          }
 
@@ -589,13 +676,51 @@ mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, Func
          */
   }
 
-  return wrap(EE);
+  *ee = wrap (EE);
+
+  return mono_ee;
 }
 
 void
-mono_llvm_dispose_ee (LLVMExecutionEngineRef ee)
+mono_llvm_dispose_ee (MonoEERef *eeref)
 {
-       delete unwrap (ee);
+       MonoEE *mono_ee = (MonoEE*)eeref;
 
-       delete fpm;
+       delete mono_ee->EE;
+       delete mono_ee->fpm;
+       //delete mono_ee->mm;
+       delete mono_ee->listener;
+       delete mono_ee;
 }
+
+#else
+
+MonoEERef
+mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb, LLVMExecutionEngineRef *ee)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+void
+mono_llvm_dispose_ee (MonoEERef *eeref)
+{
+       g_assert_not_reached ();
+}
+
+/* Not linked in */
+void
+LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global,
+                                        void* Addr)
+{
+       g_assert_not_reached ();
+}
+
+void*
+LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+#endif /* !MONO_CROSS_COMPILE */