X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-llvm-cpp.cpp;h=2b90cd692daac6ad903e56bbb23cbbb5ff4cc6e2;hb=3fa714d92208ba69e12bb18b56dd518eb91d606a;hp=86bfb1033f4b48755d906a1eea3c62da73c837e0;hpb=3c53388c59bb2886dcccd4c141b6176a4b62ad00;p=mono.git diff --git a/mono/mini/mini-llvm-cpp.cpp b/mono/mini/mini-llvm-cpp.cpp index 86bfb1033f4..2b90cd692da 100644 --- a/mono/mini/mini-llvm-cpp.cpp +++ b/mono/mini/mini-llvm-cpp.cpp @@ -1,7 +1,8 @@ // // mini-llvm-cpp.cpp: C++ support classes for the mono LLVM integration // -// (C) 2009 Novell, Inc. +// (C) 2009-2011 Novell, Inc. +// Copyright 2011 Xamarin, Inc (http://www.xamarin.com) // // @@ -19,6 +20,14 @@ // 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 #include @@ -30,6 +39,7 @@ #include #include #include +#include #include #include #include "llvm/Support/PassNameParser.h" @@ -38,7 +48,6 @@ #include #include #include -#include //#include #include "llvm-c/Core.h" @@ -46,7 +55,13 @@ #include "mini-llvm-cpp.h" -extern "C" void LLVMInitializeX86TargetInfo(); +#define LLVM_CHECK_VERSION(major,minor) \ + ((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; @@ -58,6 +73,7 @@ private: public: /* Callbacks installed by mono */ AllocCodeMemoryCb *alloc_cb; + DlSymCb *dlsym_cb; MonoJITMemoryManager (); ~MonoJITMemoryManager (); @@ -72,14 +88,6 @@ public: 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) { } @@ -105,25 +113,48 @@ public: unsigned char *TableEnd, unsigned char* FrameRegister); -#if LLVM_MAJOR_VERSION == 2 && LLVM_MINOR_VERSION >= 7 virtual void deallocateFunctionBody(void*) { } virtual void deallocateExceptionTable(void*) { } -#endif + + virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID) { + // FIXME: + assert(0); + return NULL; + } + + virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID) { + // FIXME: + assert(0); + return NULL; + } + + 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 () { -#if LLVM_MAJOR_VERSION == 2 && LLVM_MINOR_VERSION < 8 - SizeRequired = true; -#endif mm = JITMemoryManager::CreateDefaultMemManager (); } MonoJITMemoryManager::~MonoJITMemoryManager () { + delete mm; } void @@ -142,18 +173,13 @@ 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) { + // FIXME: This leaks memory + if (ActualSize == 0) + ActualSize = 128; return alloc_cb (wrap (F), ActualSize); } @@ -191,7 +217,7 @@ unsigned char* MonoJITMemoryManager::startExceptionTable(const Function* F, uintptr_t &ActualSize) { - return alloc_cb (wrap (F), ActualSize); + return startFunctionBody(F, ActualSize); } void @@ -201,7 +227,47 @@ MonoJITMemoryManager::endExceptionTable(const Function *F, unsigned char *TableS { } +class MonoJITEventListener : public JITEventListener { + +public: + FunctionEmittedCb *emitted_cb; + + MonoJITEventListener (FunctionEmittedCb *cb) { + emitted_cb = cb; + } + + 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, + * 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) +#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; @@ -216,6 +282,7 @@ void mono_llvm_dump_value (LLVMValueRef value) { /* Same as LLVMDumpValue (), but print to stdout */ + fflush (stdout); outs () << (*unwrap (value)); } @@ -254,6 +321,58 @@ mono_llvm_build_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef Po return wrap(unwrap(builder)->CreateStore(unwrap(Val), unwrap(PointerVal), is_volatile)); } +LLVMValueRef +mono_llvm_build_aligned_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef PointerVal, + gboolean is_volatile, int alignment) +{ + StoreInst *ins; + + ins = unwrap(builder)->CreateStore(unwrap(Val), unwrap(PointerVal), is_volatile); + ins->setAlignment (alignment); + + return wrap (ins); +} + +LLVMValueRef +mono_llvm_build_cmpxchg (LLVMBuilderRef builder, LLVMValueRef ptr, LLVMValueRef cmp, LLVMValueRef val) +{ + AtomicCmpXchgInst *ins; + + ins = unwrap(builder)->CreateAtomicCmpXchg (unwrap(ptr), unwrap (cmp), unwrap (val), SequentiallyConsistent); + return wrap (ins); +} + +LLVMValueRef +mono_llvm_build_atomic_rmw (LLVMBuilderRef builder, AtomicRMWOp op, LLVMValueRef ptr, LLVMValueRef val) +{ + AtomicRMWInst::BinOp aop = AtomicRMWInst::Xchg; + AtomicRMWInst *ins; + + switch (op) { + case LLVM_ATOMICRMW_OP_XCHG: + aop = AtomicRMWInst::Xchg; + break; + case LLVM_ATOMICRMW_OP_ADD: + aop = AtomicRMWInst::Add; + break; + default: + g_assert_not_reached (); + break; + } + + ins = unwrap (builder)->CreateAtomicRMW (aop, unwrap (ptr), unwrap (val), AcquireRelease); + return wrap (ins); +} + +LLVMValueRef +mono_llvm_build_fence (LLVMBuilderRef builder) +{ + FenceInst *ins; + + ins = unwrap (builder)->CreateFence (AcquireRelease); + return wrap (ins); +} + void mono_llvm_replace_uses_of (LLVMValueRef var, LLVMValueRef v) { @@ -264,45 +383,6 @@ mono_llvm_replace_uses_of (LLVMValueRef var, LLVMValueRef v) static cl::list PassList(cl::desc("Optimizations available:")); -class MonoJITEventListener : public JITEventListener { - -public: - FunctionEmittedCb *emitted_cb; - - MonoJITEventListener (FunctionEmittedCb *cb) { - emitted_cb = cb; - } - - 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, - * 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) -#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 void force_pass_linking (void) { @@ -361,7 +441,6 @@ force_pass_linking (void) (void) llvm::createLCSSAPass(); (void) llvm::createLICMPass(); (void) llvm::createLazyValueInfoPass(); - (void) llvm::createLiveValuesPass(); (void) llvm::createLoopDependenceAnalysisPass(); /* (void) llvm::createLoopExtractorPass(); @@ -371,7 +450,6 @@ force_pass_linking (void) (void) llvm::createLoopUnrollPass(); (void) llvm::createLoopUnswitchPass(); (void) llvm::createLoopRotatePass(); - (void) llvm::createLoopIndexSplitPass(); (void) llvm::createLowerInvokePass(); /* (void) llvm::createLowerSetJmpPass(); @@ -397,7 +475,6 @@ force_pass_linking (void) (void) llvm::createSCCPPass(); (void) llvm::createScalarReplAggregatesPass(); (void) llvm::createSimplifyLibCallsPass(); - (void) llvm::createSimplifyHalfPowrLibCallsPass(); /* (void) llvm::createSingleLoopExtractorPass(); (void) llvm::createStripSymbolsPass(); @@ -428,71 +505,121 @@ force_pass_linking (void) (void) llvm::createDbgInfoPrinterPass(); (void) llvm::createModuleDebugInfoPrinterPass(); (void) llvm::createPartialInliningPass(); - */ - (void) llvm::createSSIPass(); - (void) llvm::createSSIEverythingPass(); (void) llvm::createGEPSplitterPass(); - (void) llvm::createABCDPass(); - /* (void) llvm::createLintPass(); */ (void) llvm::createSinkingPass(); } LLVMExecutionEngineRef -mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb) +mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb) { std::string Error; force_pass_linking (); +#ifdef TARGET_ARM + LLVMInitializeARMTarget (); + LLVMInitializeARMTargetInfo (); + LLVMInitializeARMTargetMC (); +#else LLVMInitializeX86Target (); LLVMInitializeX86TargetInfo (); - - llvm::cl::ParseEnvironmentOptions("mono", "MONO_LLVM", "", false); + LLVMInitializeX86TargetMC (); +#endif mono_mm = new MonoJITMemoryManager (); mono_mm->alloc_cb = alloc_cb; + mono_mm->dlsym_cb = dlsym_cb; -#if LLVM_MAJOR_VERSION == 2 && LLVM_MINOR_VERSION < 8 - DwarfExceptionHandling = true; -#else - JITExceptionHandling = true; -#endif + //JITExceptionHandling = true; // PrettyStackTrace installs signal handlers which trip up libgc DisablePrettyStackTrace = true; - ExecutionEngine *EE = ExecutionEngine::createJIT (unwrap (MP), &Error, mono_mm, CodeGenOpt::Default); + /* + * The Default code model doesn't seem to work on amd64, + * test_0_fields_with_big_offsets (among others) crashes, because LLVM tries to call + * memset using a normal pcrel code which is in 32bit memory, while memset isn't. + */ + + TargetOptions opts; + opts.JITExceptionHandling = 1; + + EngineBuilder b (unwrap (MP)); +#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 (); +#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 + EE->InstallExceptionTableRegister (exception_cb); - EE->RegisterJITEventListener (new MonoJITEventListener (emitted_cb)); + mono_event_listener = new MonoJITEventListener (emitted_cb); + EE->RegisterJITEventListener (mono_event_listener); fpm = new FunctionPassManager (unwrap (MP)); fpm->add(new TargetData(*EE->getTargetData())); - /* Add a default set of passes */ - //createStandardFunctionPasses (fpm, 2); - fpm->add(createInstructionCombiningPass()); - fpm->add(createReassociatePass()); - fpm->add(createGVNPass()); - fpm->add(createCFGSimplificationPass()); - - /* The one used by opt is: - * -simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -basiccg -domtree -domfrontier -scalarrepl -simplify-libcalls -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loopsimplify -domfrontier -loopsimplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loopsimplify -lcssa -iv-users -indvars -loop-deletion -loopsimplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -gvn -simplifycfg -preverify -domtree -verify - */ - /* Add passes specified by the env variable */ - /* Only the passes in force_pass_linking () can be used */ - for (unsigned i = 0; i < PassList.size(); ++i) { - const PassInfo *PassInf = PassList[i]; - Pass *P = 0; + PassRegistry &Registry = *PassRegistry::getPassRegistry(); + initializeCore(Registry); + initializeScalarOpts(Registry); + //initializeIPO(Registry); + initializeAnalysis(Registry); + initializeIPA(Registry); + initializeTransformUtils(Registry); + initializeInstCombine(Registry); + //initializeInstrumentation(Registry); + initializeTarget(Registry); - if (PassInf->getNormalCtor()) - P = PassInf->getNormalCtor()(); - fpm->add (P); + llvm::cl::ParseEnvironmentOptions("mono", "MONO_LLVM", "", false); + + if (PassList.size() > 0) { + /* Use the passes specified by the env variable */ + /* Only the passes in force_pass_linking () can be used */ + for (unsigned i = 0; i < PassList.size(); ++i) { + const PassInfo *PassInf = PassList[i]; + Pass *P = 0; + + if (PassInf->getNormalCtor()) + P = PassInf->getNormalCtor()(); + fpm->add (P); + } + } 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"; + char **args; + int i; + + args = g_strsplit (opts, " ", 1000); + for (i = 0; args [i]; i++) + ; + llvm::cl::ParseCommandLineOptions (i, args, "", false); + g_strfreev (args); + + for (unsigned i = 0; i < PassList.size(); ++i) { + const PassInfo *PassInf = PassList[i]; + Pass *P = 0; + + if (PassInf->getNormalCtor()) + P = PassInf->getNormalCtor()(); + fpm->add (P); + } + + /* + fpm->add(createInstructionCombiningPass()); + fpm->add(createReassociatePass()); + fpm->add(createGVNPass()); + fpm->add(createCFGSimplificationPass()); + */ } return wrap(EE);