X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fllvm-jit.cpp;h=7fef6b85cb9741b955d701ae1082822fea5cca66;hb=dfac8517b91687f11479801fa0a2191585b1ad4c;hp=ed719f456e4156a74ee358f1d7b847a4395cfe2f;hpb=5a9dfc17d956ff8f7b1dc4b48964393ed89ce07f;p=mono.git diff --git a/mono/mini/llvm-jit.cpp b/mono/mini/llvm-jit.cpp index ed719f456e4..7fef6b85cb9 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 @@ -31,42 +31,173 @@ #include "llvm/ExecutionEngine/Orc/CompileUtils.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" #include "llvm/ExecutionEngine/Orc/LambdaResolver.h" -#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" #include "llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h" +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) -{ - if (inited) - return; +#ifdef __MINGW32__ - InitializeNativeTarget (); - InitializeNativeTargetAsmPrinter(); -} +#include +extern void *memset(void *, int, size_t); +void bzero (void *to, size_t count) { memset (to, 0, count); } + +#endif + +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) { - init_llvm (); + 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; } -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 @@ -75,13 +206,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;