[llvm] Add support for JIT + LLVM 9.0. (mono/mono#15997)
authorimhameed <50922266+imhameed@users.noreply.github.com>
Sat, 3 Aug 2019 15:58:40 +0000 (08:58 -0700)
committerZoltan Varga <vargaz@gmail.com>
Sat, 3 Aug 2019 15:58:40 +0000 (11:58 -0400)
* [llvm] Add support for llvm 9.0.

Works with this branch:
https://github.com/mono/llvm/tree/release_90

* Add support for JIT + LLVM 9.

* Don't assume that all memset targets will be aligned; fixes LLVM 6 on amd64.

Commit migrated from https://github.com/mono/mono/commit/3ab93f97e681868216327b8b0b7c19112ccfc1d3

src/mono/mono/mini/llvm-jit.cpp
src/mono/mono/mini/mini-llvm-cpp.cpp
src/mono/mono/mini/mini-llvm.c

index 368c8c4..c35abbf 100644 (file)
@@ -114,6 +114,132 @@ MonoJitMemoryManager::finalizeMemory(std::string *ErrMsg)
        return false;
 }
 
+#if LLVM_API_VERSION >= 900
+
+struct MonoLLVMJIT {
+       std::shared_ptr<MonoJitMemoryManager> mmgr;
+       ExecutionSession execution_session;
+       std::map<VModuleKey, std::shared_ptr<SymbolResolver>> resolvers;
+       TargetMachine *target_machine;
+       LegacyRTDyldObjectLinkingLayer object_layer;
+       LegacyIRCompileLayer<decltype(object_layer), SimpleCompiler> compile_layer;
+       DataLayout data_layout;
+
+       MonoLLVMJIT (TargetMachine *tm)
+               : mmgr (std::make_shared<MonoJitMemoryManager>())
+               , target_machine (tm)
+               , object_layer (
+                       AcknowledgeORCv1Deprecation, execution_session,
+                       [this] (VModuleKey k) {
+                               return LegacyRTDyldObjectLinkingLayer::Resources{
+                                       mmgr, resolvers[k] };
+                       })
+               , compile_layer (
+                       AcknowledgeORCv1Deprecation, object_layer,
+                       SimpleCompiler{*target_machine})
+               , data_layout (target_machine->createDataLayout())
+       {
+               compile_layer.setNotifyCompiled ([] (VModuleKey, std::unique_ptr<Module> module) {
+                       module.release ();
+               });
+       }
+
+       VModuleKey
+       add_module (std::unique_ptr<Module> m)
+       {
+               auto k = execution_session.allocateVModule();
+               auto lookup_name = [this] (const std::string &namestr) {
+                       auto jit_sym = compile_layer.findSymbol(namestr, false);
+                       if (jit_sym) {
+                               return jit_sym;
+                       }
+                       auto namebuf = namestr.c_str();
+                       JITSymbolFlags flags{};
+                       if (!strcmp(namebuf, "___bzero")) {
+                               return JITSymbol{(uint64_t)(gssize)(void*)bzero, flags};
+                       }
+                       auto current = mono_dl_open (NULL, 0, NULL);
+                       g_assert (current);
+                       auto name = namebuf[0] == '_' ? namebuf + 1 : namebuf;
+                       void *sym = nullptr;
+                       auto err = mono_dl_symbol (current, name, &sym);
+                       if (!sym) {
+                               outs () << "R: " << namestr << "\n";
+                       }
+                       assert (sym);
+                       return JITSymbol{(uint64_t)(gssize)sym, flags};
+               };
+               auto on_error = [] (Error err) {
+                       outs () << "R2: " << err << "\n";
+                       assert (0);
+               };
+               auto resolver = createLegacyLookupResolver (execution_session,
+                       lookup_name, on_error);
+               resolvers[k] = std::move (resolver);
+               compile_layer.addModule (k, std::move(m));
+               return k;
+       }
+
+       std::string
+       mangle (const std::string &name)
+       {
+               std::string ret;
+               raw_string_ostream out{ret};
+               Mangler::getNameWithPrefix (out, name, data_layout);
+               return ret;
+       }
+
+       std::string
+       mangle (const GlobalValue *gv)
+       {
+               std::string ret;
+               raw_string_ostream out{ret};
+               Mangler{}.getNameWithPrefix (out, gv, false);
+               return ret;
+       }
+
+       gpointer
+       compile (
+               Function *func, int nvars, LLVMValueRef *callee_vars,
+               gpointer *callee_addrs, gpointer *eh_frame)
+       {
+               auto module = func->getParent ();
+               module->setDataLayout (data_layout);
+               // The lifetime of this module is managed by the C API, and the
+               // `unique_ptr` created here will be released in the
+               // NotifyCompiled callback.
+               auto k = add_module (std::unique_ptr<Module>(module));
+               auto bodysym = compile_layer.findSymbolIn (k, mangle (func), false);
+               auto bodyaddr = bodysym.getAddress ();
+               assert (bodyaddr);
+               for (int i = 0; i < nvars; ++i) {
+                       auto var = unwrap<GlobalVariable> (callee_vars[i]);
+                       auto sym = compile_layer.findSymbolIn (k, mangle (var->getName ()), true);
+                       auto addr = sym.getAddress ();
+                       g_assert ((bool)addr);
+                       callee_addrs[i] = (gpointer)addr.get ();
+               }
+               auto ehsym = compile_layer.findSymbolIn (k, "mono_eh_frame", false);
+               auto ehaddr = ehsym.getAddress ();
+               g_assert ((bool)ehaddr);
+               *eh_frame = (gpointer)ehaddr.get ();
+               return (gpointer)bodyaddr.get ();
+       }
+};
+
+static void
+init_mono_llvm_jit ()
+{
+}
+
+static MonoLLVMJIT *
+make_mono_llvm_jit (TargetMachine *target_machine)
+{
+       return new MonoLLVMJIT{target_machine};
+}
+
+#elif LLVM_API_VERSION > 600
+
 class MonoLLVMJIT {
 public:
        /* We use our own trampoline infrastructure instead of the Orc one */
@@ -215,9 +341,24 @@ private:
        std::vector<std::shared_ptr<Module>> modules;
 };
 
-static MonoLLVMJIT *jit;
 static MonoJitMemoryManager *mono_mm;
 
+static void
+init_mono_llvm_jit ()
+{
+       mono_mm = new MonoJitMemoryManager ();
+}
+
+static MonoLLVMJIT *
+make_mono_llvm_jit (TargetMachine *target_machine)
+{
+       return new MonoLLVMJIT(target_machine, mono_mm);
+}
+
+#endif
+
+static MonoLLVMJIT *jit;
+
 MonoEERef
 mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, LLVMExecutionEngineRef *ee)
 {
@@ -240,8 +381,8 @@ mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, Func
        auto TM = EB.selectTarget ();
        assert (TM);
 
-       mono_mm = new MonoJitMemoryManager ();
-       jit = new MonoLLVMJIT (TM, mono_mm);
+       init_mono_llvm_jit ();
+       jit = make_mono_llvm_jit (TM);
 
        return NULL;
 }
index 71987ae..e3dee6a 100644 (file)
@@ -441,7 +441,11 @@ mono_llvm_di_create_function (void *di_builder, void *cu, LLVMValueRef func, con
        // FIXME: Share DIFile
        di_file = builder->createFile (file, dir);
        type = builder->createSubroutineType (builder->getOrCreateTypeArray (ArrayRef<Metadata*> ()));
+#if LLVM_API_VERSION >= 900
+       di_func = builder->createFunction (di_file, name, mangled_name, di_file, line, type, 0);
+#else
        di_func = builder->createFunction (di_file, name, mangled_name, di_file, line, type, true, true, 0);
+#endif
 
        unwrap<Function>(func)->setMetadata ("dbg", di_func);
 
@@ -479,8 +483,13 @@ mono_llvm_di_builder_finalize (void *di_builder)
 LLVMValueRef
 mono_llvm_get_or_insert_gc_safepoint_poll (LLVMModuleRef module)
 {
-       llvm::Constant *SafepointPollConstant;
+#if LLVM_API_VERSION >= 900
+
+       llvm::FunctionCallee callee = unwrap(module)->getOrInsertFunction("gc.safepoint_poll", FunctionType::get(unwrap(LLVMVoidType()), false));
+       return wrap (dyn_cast<llvm::Function> (callee.getCallee ()));
+#else
        llvm::Function *SafepointPoll;
+       llvm::Constant *SafepointPollConstant;
 
        SafepointPollConstant = unwrap(module)->getOrInsertFunction("gc.safepoint_poll", FunctionType::get(unwrap(LLVMVoidType()), false));
        g_assert (SafepointPollConstant);
@@ -490,4 +499,5 @@ mono_llvm_get_or_insert_gc_safepoint_poll (LLVMModuleRef module)
        g_assert (SafepointPoll->empty());
 
        return wrap(SafepointPoll);
+#endif
 }
index 9b8f4e2..49f2afc 100644 (file)
@@ -384,6 +384,12 @@ set_failure (EmitContext *ctx, const char *message)
        ctx->cfg->disable_llvm = TRUE;
 }
 
+static LLVMValueRef
+ConstInt32 (int v)
+{
+       return LLVMConstInt (LLVMInt32Type (), v, FALSE);
+}
+
 /*
  * IntPtrType:
  *
@@ -1285,6 +1291,22 @@ convert (EmitContext *ctx, LLVMValueRef v, LLVMTypeRef dtype)
        return convert_full (ctx, v, dtype, FALSE);
 }
 
+static void
+emit_memset (EmitContext *ctx, LLVMBuilderRef builder, LLVMValueRef v, LLVMValueRef size, int alignment)
+{
+       LLVMValueRef args [5];
+       int aindex = 0;
+
+       args [aindex ++] = v;
+       args [aindex ++] = LLVMConstInt (LLVMInt8Type (), 0, FALSE);
+       args [aindex ++] = size;
+#if LLVM_API_VERSION < 900
+       args [aindex ++] = LLVMConstInt (LLVMInt32Type (), alignment, FALSE);
+#endif
+       args [aindex ++] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
+       LLVMBuildCall (builder, get_intrins (ctx, INTRINS_MEMSET), args, aindex, "");
+}
+
 /*
  * emit_volatile_load:
  *
@@ -5556,16 +5578,8 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
 
                        v = mono_llvm_build_alloca (builder, LLVMInt8Type (), LLVMConstInt (LLVMInt32Type (), size, FALSE), MONO_ARCH_FRAME_ALIGNMENT, "");
 
-                       if (ins->flags & MONO_INST_INIT) {
-                               LLVMValueRef args [5];
-
-                               args [0] = v;
-                               args [1] = LLVMConstInt (LLVMInt8Type (), 0, FALSE);
-                               args [2] = LLVMConstInt (LLVMInt32Type (), size, FALSE);
-                               args [3] = LLVMConstInt (LLVMInt32Type (), MONO_ARCH_FRAME_ALIGNMENT, FALSE);
-                               args [4] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
-                               LLVMBuildCall (builder, get_intrins (ctx, INTRINS_MEMSET), args, 5, "");
-                       }
+                       if (ins->flags & MONO_INST_INIT)
+                               emit_memset (ctx, builder, v, ConstInt32 (size), MONO_ARCH_FRAME_ALIGNMENT);
 
                        values [ins->dreg] = v;
                        break;
@@ -5577,16 +5591,8 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
 
                        v = mono_llvm_build_alloca (builder, LLVMInt8Type (), size, MONO_ARCH_FRAME_ALIGNMENT, "");
 
-                       if (ins->flags & MONO_INST_INIT) {
-                               LLVMValueRef args [5];
-
-                               args [0] = v;
-                               args [1] = LLVMConstInt (LLVMInt8Type (), 0, FALSE);
-                               args [2] = size;
-                               args [3] = LLVMConstInt (LLVMInt32Type (), MONO_ARCH_FRAME_ALIGNMENT, FALSE);
-                               args [4] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
-                               LLVMBuildCall (builder, get_intrins (ctx, INTRINS_MEMSET), args, 5, "");
-                       }
+                       if (ins->flags & MONO_INST_INIT)
+                               emit_memset (ctx, builder, v, size, MONO_ARCH_FRAME_ALIGNMENT);
                        values [ins->dreg] = v;
                        break;
                }
@@ -6214,7 +6220,6 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                         */
                case OP_VZERO: {
                        MonoClass *klass = ins->klass;
-                       LLVMValueRef args [5];
 
                        if (!klass) {
                                // FIXME:
@@ -6224,13 +6229,8 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
 
                        if (!addresses [ins->dreg])
                                addresses [ins->dreg] = build_alloca (ctx, m_class_get_byval_arg (klass));
-                       args [0] = LLVMBuildBitCast (builder, addresses [ins->dreg], LLVMPointerType (LLVMInt8Type (), 0), "");
-                       args [1] = LLVMConstInt (LLVMInt8Type (), 0, FALSE);
-                       args [2] = LLVMConstInt (LLVMInt32Type (), mono_class_value_size (klass, NULL), FALSE);
-                       // FIXME: Alignment
-                       args [3] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
-                       args [4] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
-                       LLVMBuildCall (builder, get_intrins (ctx, INTRINS_MEMSET), args, 5, "");
+                       LLVMValueRef ptr = LLVMBuildBitCast (builder, addresses [ins->dreg], LLVMPointerType (LLVMInt8Type (), 0), "");
+                       emit_memset (ctx, builder, ptr, ConstInt32 (mono_class_value_size (klass, NULL)), 0);
                        break;
                }
                case OP_DUMMY_VZERO:
@@ -6297,14 +6297,16 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        if (done)
                                break;
 
-                       args [0] = dst;
-                       args [1] = src;
-                       args [2] = LLVMConstInt (LLVMInt32Type (), mono_class_value_size (klass, NULL), FALSE);
-                       args [3] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
+                       int aindex = 0;
+                       args [aindex ++] = dst;
+                       args [aindex ++] = src;
+                       args [aindex ++] = LLVMConstInt (LLVMInt32Type (), mono_class_value_size (klass, NULL), FALSE);
+#if LLVM_API_VERSION < 900
                        // FIXME: Alignment
-                       args [3] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
-                       args [4] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
-                       LLVMBuildCall (builder, get_intrins (ctx, INTRINS_MEMCPY), args, 5, "");
+                       args [aindex ++] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
+#endif
+                       args [aindex ++] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
+                       LLVMBuildCall (builder, get_intrins (ctx, INTRINS_MEMCPY), args, aindex, "");
                        break;
                }
                case OP_LLVM_OUTARG_VT: {
@@ -8279,15 +8281,29 @@ add_intrinsic (LLVMModuleRef module, int id)
 
        switch (id) {
        case INTRINS_MEMSET: {
+#if LLVM_API_VERSION >= 900
+               /* No alignment argument */
+               LLVMTypeRef params [] = { LLVMPointerType (LLVMInt8Type (), 0), LLVMInt8Type (), LLVMInt32Type (), LLVMInt1Type () };
+
+               AddFunc (module, name, LLVMVoidType (), params, 4);
+#else
                LLVMTypeRef params [] = { LLVMPointerType (LLVMInt8Type (), 0), LLVMInt8Type (), LLVMInt32Type (), LLVMInt32Type (), LLVMInt1Type () };
 
                AddFunc (module, name, LLVMVoidType (), params, 5);
+#endif
                break;
        }
        case INTRINS_MEMCPY: {
+#if LLVM_API_VERSION >= 900
+               /* No alignment argument */
+               LLVMTypeRef params [] = { LLVMPointerType (LLVMInt8Type (), 0), LLVMPointerType (LLVMInt8Type (), 0), LLVMInt32Type (), LLVMInt1Type () };
+
+               AddFunc (module, name, LLVMVoidType (), params, 4);
+#else
                LLVMTypeRef params [] = { LLVMPointerType (LLVMInt8Type (), 0), LLVMPointerType (LLVMInt8Type (), 0), LLVMInt32Type (), LLVMInt32Type (), LLVMInt1Type () };
 
                AddFunc (module, name, LLVMVoidType (), params, 5);
+#endif
                break;
        }
        case INTRINS_SADD_OVF_I32: