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 */
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)
{
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;
}
// 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);
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);
g_assert (SafepointPoll->empty());
return wrap(SafepointPoll);
+#endif
}
ctx->cfg->disable_llvm = TRUE;
}
+static LLVMValueRef
+ConstInt32 (int v)
+{
+ return LLVMConstInt (LLVMInt32Type (), v, FALSE);
+}
+
/*
* IntPtrType:
*
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:
*
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;
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;
}
*/
case OP_VZERO: {
MonoClass *klass = ins->klass;
- LLVMValueRef args [5];
if (!klass) {
// FIXME:
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:
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: {
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: