X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fllvm-jit.cpp;h=868097e617085fc86c9dfb0007a9666922bce742;hb=222df67b5f5a9bd5e2c8da9e454b0f2883e1fe41;hp=d4ba5599049ef11e6221d7c565a9b3a0c76fcb06;hpb=5317fbc0cd0146c84ffab2dc1776ec34cce859c0;p=mono.git diff --git a/mono/mini/llvm-jit.cpp b/mono/mini/llvm-jit.cpp index d4ba5599049..868097e6170 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,8 +16,266 @@ #include #include "mini-llvm-cpp.h" +#include "llvm-jit.h" + +#if !defined(MONO_CROSS_COMPILE) && LLVM_API_VERSION > 100 + +/* + * LLVM 3.9 uses the OrcJIT APIs + */ + +#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/ObjectLinkingLayer.h" + +#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) +{ +} + +template +static std::vector singletonSet(T t) { + std::vector Vec; + Vec.push_back(std::move(t)); + return Vec; +} + +#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 +{ +public: + ~MonoJitMemoryManager() override; -#if !defined(MONO_CROSS_COMPILE) && LLVM_API_VERSION < 100 + 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 */ + typedef ObjectLinkingLayer<> ObjLayerT; + typedef IRCompileLayer CompileLayerT; + typedef CompileLayerT::ModuleSetHandleT ModuleHandleT; + + MonoLLVMJIT (TargetMachine *TM) + : TM(TM), + CompileLayer (ObjectLayer, SimpleCompiler (*TM)) { + } + + ModuleHandleT addModule(Module *M) { + auto Resolver = createLambdaResolver( + [&](const std::string &Name) { + const char *name = Name.c_str (); + if (!strcmp (name, "___bzero")) + return RuntimeDyld::SymbolInfo((uint64_t)(gssize)(void*)bzero, (JITSymbolFlags)0); + + 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); + return RuntimeDyld::SymbolInfo((uint64_t)(gssize)symbol, (JITSymbolFlags)0); + }, + [](const std::string &S) { + outs () << "R2: " << S << "\n"; + assert (0); + return nullptr; + } ); + + return CompileLayer.addModuleSet(singletonSet(M), + make_unique(), + std::move(Resolver)); + } + + 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 ()); + auto ModuleHandle = addModule (F->getParent ()); + + 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; +}; + +static MonoLLVMJIT *jit; + +MonoEERef +mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb, LLVMExecutionEngineRef *ee) +{ + 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); + + jit = new MonoLLVMJIT (TM); + + return NULL; +} + +/* + * 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) +{ + return jit->compile (unwrap (method), nvars, callee_vars, callee_addrs, eh_frame); +} + +void +mono_llvm_dispose_ee (MonoEERef *eeref) +{ +} + +void +LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, + void* Addr) +{ + g_assert_not_reached (); +} + +void* +LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global) +{ + g_assert_not_reached (); + return NULL; +} + +#elif !defined(MONO_CROSS_COMPILE) && LLVM_API_VERSION < 100 #include @@ -555,6 +813,14 @@ mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, Func void 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