X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fllvm-jit.cpp;h=e09d72e9192f97b23ef69eb35c1e97ee6d66b831;hb=098f6e8aa8ead1a80b751fa34e5e049439c2f0c3;hp=22ef4b284110184d10872aa1f3e81b71c45dba54;hpb=3df1a68186f4f14817df6f6d93773a46937d498e;p=mono.git diff --git a/mono/mini/llvm-jit.cpp b/mono/mini/llvm-jit.cpp index 22ef4b28411..e09d72e9192 100644 --- a/mono/mini/llvm-jit.cpp +++ b/mono/mini/llvm-jit.cpp @@ -4,7 +4,7 @@ // (C) 2009-2011 Novell, Inc. // Copyright 2011-2015 Xamarin, Inc (http://www.xamarin.com) // - +// Licensed under the MIT license. See LICENSE file in the project root for full license information. // // Mono's internal header files are not C++ clean, so avoid including them if // possible @@ -16,6 +16,7 @@ #include #include "mini-llvm-cpp.h" +#include "llvm-jit.h" #if !defined(MONO_CROSS_COMPILE) && LLVM_API_VERSION > 100 @@ -26,46 +27,283 @@ #include #include #include +#include #include #include "llvm/ExecutionEngine/Orc/CompileUtils.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" #include "llvm/ExecutionEngine/Orc/LambdaResolver.h" -#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" +#if LLVM_API_VERSION >= 500 +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" +#include "llvm/ExecutionEngine/JITSymbol.h" +#else #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" -#include "llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h" +#endif + +#include + +extern "C" { +#include +} using namespace llvm; using namespace llvm::orc; +extern cl::opt EnableMonoEH; +extern cl::opt MonoEHFrameSymbol; + void mono_llvm_set_unhandled_exception_handler (void) { } -static gboolean inited; +template +static std::vector singletonSet(T t) { + std::vector Vec; + Vec.push_back(std::move(t)); + return Vec; +} -static void -init_llvm (void) +#ifdef __MINGW32__ + +#include +extern void *memset(void *, int, size_t); +void bzero (void *to, size_t count) { memset (to, 0, count); } + +#endif + +static AllocCodeMemoryCb *alloc_code_mem_cb; + +class MonoJitMemoryManager : public RTDyldMemoryManager { - if (inited) - return; +public: + ~MonoJitMemoryManager() override; - InitializeNativeTarget (); - InitializeNativeTargetAsmPrinter(); + uint8_t *allocateDataSection(uintptr_t Size, + unsigned Alignment, + unsigned SectionID, + StringRef SectionName, + bool IsReadOnly) override; + + uint8_t *allocateCodeSection(uintptr_t Size, + unsigned Alignment, + unsigned SectionID, + StringRef SectionName) override; + + bool finalizeMemory(std::string *ErrMsg = nullptr) override; +}; + +MonoJitMemoryManager::~MonoJitMemoryManager() +{ +} + +uint8_t * +MonoJitMemoryManager::allocateDataSection(uintptr_t Size, + unsigned Alignment, + unsigned SectionID, + StringRef SectionName, + bool IsReadOnly) { + uint8_t *res = (uint8_t*)malloc (Size); + assert (res); + memset (res, 0, Size); + return res; +} + +uint8_t * +MonoJitMemoryManager::allocateCodeSection(uintptr_t Size, + unsigned Alignment, + unsigned SectionID, + StringRef SectionName) +{ + return alloc_code_mem_cb (NULL, Size); +} + +bool +MonoJitMemoryManager::finalizeMemory(std::string *ErrMsg) +{ + return false; } +class MonoLLVMJIT { +public: + /* We use our own trampoline infrastructure instead of the Orc one */ +#if LLVM_API_VERSION >= 500 + typedef RTDyldObjectLinkingLayer ObjLayerT; + typedef IRCompileLayer CompileLayerT; + typedef CompileLayerT::ModuleHandleT ModuleHandleT; +#else + typedef ObjectLinkingLayer<> ObjLayerT; + typedef IRCompileLayer CompileLayerT; + typedef CompileLayerT::ModuleSetHandleT ModuleHandleT; +#endif + + MonoLLVMJIT (TargetMachine *TM, MonoJitMemoryManager *mm) +#if LLVM_API_VERSION >= 500 + : TM(TM), ObjectLayer([=] { return std::shared_ptr (mm); }), +#else + : TM(TM), +#endif + CompileLayer (ObjectLayer, SimpleCompiler (*TM)), + modules() { + } + +#if LLVM_API_VERSION >= 500 + ModuleHandleT addModule(Function *F, std::shared_ptr M) { +#else + ModuleHandleT addModule(Function *F, Module *M) { +#endif + auto Resolver = createLambdaResolver( + [&](const std::string &Name) { + const char *name = Name.c_str (); +#if LLVM_API_VERSION >= 500 + JITSymbolFlags flags = JITSymbolFlags (); +#else + JITSymbolFlags flags = (JITSymbolFlags)0; +#endif + if (!strcmp (name, "___bzero")) { +#if LLVM_API_VERSION >= 500 + return JITSymbol((uint64_t)(gssize)(void*)bzero, flags); +#else + return RuntimeDyld::SymbolInfo((uint64_t)(gssize)(void*)bzero, flags); +#endif + } + + MonoDl *current; + char *err; + void *symbol; + current = mono_dl_open (NULL, 0, NULL); + g_assert (current); + if (name [0] == '_') + err = mono_dl_symbol (current, name + 1, &symbol); + else + err = mono_dl_symbol (current, name, &symbol); + mono_dl_close (current); + if (!symbol) + outs () << "R: " << Name << "\n"; + assert (symbol); +#if LLVM_API_VERSION >= 500 + return JITSymbol((uint64_t)(gssize)symbol, flags); +#else + return RuntimeDyld::SymbolInfo((uint64_t)(gssize)symbol, flags); +#endif + }, + [](const std::string &S) { + outs () << "R2: " << S << "\n"; + assert (0); + return nullptr; + } ); + +#if LLVM_API_VERSION >= 500 + ModuleHandleT m = CompileLayer.addModule(M, + std::move(Resolver)); + return m; +#else + return CompileLayer.addModuleSet(singletonSet(M), + make_unique(), + std::move(Resolver)); +#endif + } + + std::string mangle(const std::string &Name) { + std::string MangledName; + { + raw_string_ostream MangledNameStream(MangledName); + Mangler::getNameWithPrefix(MangledNameStream, Name, + TM->createDataLayout()); + } + return MangledName; + } + + std::string mangle(const GlobalValue *GV) { + std::string MangledName; + { + Mangler Mang; + + raw_string_ostream MangledNameStream(MangledName); + Mang.getNameWithPrefix(MangledNameStream, GV, false); + } + return MangledName; + } + + gpointer compile (Function *F, int nvars, LLVMValueRef *callee_vars, gpointer *callee_addrs, gpointer *eh_frame) { + F->getParent ()->setDataLayout (TM->createDataLayout ()); +#if LLVM_API_VERSION >= 500 + // Orc uses a shared_ptr to refer to modules so we have to save them ourselves to keep a ref + std::shared_ptr m (F->getParent ()); + modules.push_back (m); + auto ModuleHandle = addModule (F, m); +#else + auto ModuleHandle = addModule (F, F->getParent ()); +#endif + auto BodySym = CompileLayer.findSymbolIn(ModuleHandle, mangle (F), false); + auto BodyAddr = BodySym.getAddress(); + assert (BodyAddr); + + for (int i = 0; i < nvars; ++i) { + GlobalVariable *var = unwrap(callee_vars [i]); + + auto sym = CompileLayer.findSymbolIn (ModuleHandle, mangle (var->getName ()), true); + auto addr = sym.getAddress (); + g_assert (addr); + callee_addrs [i] = (gpointer)addr; + } + + auto ehsym = CompileLayer.findSymbolIn(ModuleHandle, "mono_eh_frame", false); + auto ehaddr = ehsym.getAddress (); + g_assert (ehaddr); + *eh_frame = (gpointer)ehaddr; + + return (gpointer)BodyAddr; + } + +private: + TargetMachine *TM; + ObjLayerT ObjectLayer; + CompileLayerT CompileLayer; + std::vector> modules; +}; + +static MonoLLVMJIT *jit; +static MonoJitMemoryManager *mono_mm; + MonoEERef mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb, LLVMExecutionEngineRef *ee) { - init_llvm (); + alloc_code_mem_cb = alloc_cb; + + InitializeNativeTarget (); + InitializeNativeTargetAsmPrinter(); + + EnableMonoEH = true; + MonoEHFrameSymbol = "mono_eh_frame"; + + EngineBuilder EB; +#if defined(TARGET_AMD64) || defined(TARGET_X86) + std::vector attrs; + // FIXME: Autodetect this + attrs.push_back("sse3"); + attrs.push_back("sse4.1"); + EB.setMAttrs (attrs); +#endif + auto TM = EB.selectTarget (); + assert (TM); + + mono_mm = new MonoJitMemoryManager (); + jit = new MonoLLVMJIT (TM, mono_mm); return NULL; } -void -mono_llvm_optimize_method (MonoEERef eeref, LLVMValueRef method) +/* + * mono_llvm_compile_method: + * + * Compile METHOD to native code. Compute the addresses of the variables in CALLEE_VARS and store them into + * CALLEE_ADDRS. Return the EH frame address in EH_FRAME. + */ +gpointer +mono_llvm_compile_method (MonoEERef mono_ee, LLVMValueRef method, int nvars, LLVMValueRef *callee_vars, gpointer *callee_addrs, gpointer *eh_frame) { - g_assert_not_reached (); + return jit->compile (unwrap (method), nvars, callee_vars, callee_addrs, eh_frame); } void @@ -74,13 +312,14 @@ mono_llvm_dispose_ee (MonoEERef *eeref) } void -LLVMAddGlobalMapping (LLVMExecutionEngineRef EE, LLVMValueRef Global, - void* Addr) +LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, + void* Addr) { + g_assert_not_reached (); } void* -LLVMGetPointerToGlobal (LLVMExecutionEngineRef EE, LLVMValueRef Global) +LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global) { g_assert_not_reached (); return NULL; @@ -341,7 +580,11 @@ static void force_pass_linking (void) { // Make sure the rest is linked in, but never executed - if (g_getenv ("FOO") != (char*)-1) + char *foo = g_getenv ("FOO"); + gboolean ret = (foo != (char*)-1); + g_free (foo); + + if (ret) return; // This is a subset of the passes in LinkAllPasses.h @@ -627,6 +870,13 @@ mono_llvm_optimize_method (MonoEERef eeref, LLVMValueRef method) g_assert_not_reached (); } +gpointer +mono_llvm_compile_method (MonoEERef mono_ee, LLVMValueRef method, int nvars, LLVMValueRef *callee_vars, gpointer *callee_addrs, gpointer *eh_frame) +{ + g_assert_not_reached (); + return NULL; +} + void mono_llvm_dispose_ee (MonoEERef *eeref) {