From 4422a1d2c831999245b2cff647bd6d9259d553a2 Mon Sep 17 00:00:00 2001 From: pchintalapudi <34727397+pchintalapudi@users.noreply.github.com> Date: Fri, 1 Apr 2022 18:02:52 -0400 Subject: [PATCH] Migrate codegen to operate on orc::ThreadSafeModule (#44440) * Move to TSModule, round 2 * Pass in modules to codegen * Rename jl_create_datalayout * Get unlocked modules once * Pass along module data layout and target more frequently * Remove jl_get_ee_context * Add note about context locks --- doc/src/devdocs/locks.md | 5 + src/aotcompile.cpp | 125 ++++++++-------- src/ccall.cpp | 31 ++-- src/codegen-stubs.c | 11 +- src/codegen.cpp | 131 ++++++++-------- src/disasm.cpp | 27 ++-- src/jitlayers.cpp | 191 +++++++++++++----------- src/jitlayers.h | 59 +++++--- src/jl_exported_funcs.inc | 2 - src/julia_internal.h | 8 +- src/runtime_intrinsics.c | 2 +- stdlib/InteractiveUtils/src/codeview.jl | 6 +- 12 files changed, 325 insertions(+), 273 deletions(-) diff --git a/doc/src/devdocs/locks.md b/doc/src/devdocs/locks.md index 0e9f04c8e402b..e9b557bcdd4f0 100644 --- a/doc/src/devdocs/locks.md +++ b/doc/src/devdocs/locks.md @@ -47,6 +47,11 @@ The following is a level 4 lock, which can only recurse to acquire level 1, 2, o No Julia code may be called while holding a lock above this point. +orc::ThreadSafeContext locks occupy a special spot in the locking diagram. They are used to protect +LLVM's global non-threadsafe state, but there may be an arbitrary number of them. For now, there is +only one global context, and thus acquiring it is a level 5 lock. However, acquiring such a lock +should only be done at the same time that the codegen lock is acquired. + The following are a level 6 lock, which can only recurse to acquire locks at lower levels: > * codegen diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp index 8388f238c25de..0f8ffea7510c6 100644 --- a/src/aotcompile.cpp +++ b/src/aotcompile.cpp @@ -77,7 +77,7 @@ static T *addComdat(T *G) typedef struct { - std::unique_ptr M; + orc::ThreadSafeModule M; std::vector jl_sysimg_fvars; std::vector jl_sysimg_gvars; std::map> jl_fvar_map; @@ -113,11 +113,11 @@ int32_t jl_get_llvm_gv_impl(void *native_code, jl_value_t *p) } extern "C" JL_DLLEXPORT -Module* jl_get_llvm_module_impl(void *native_code) +LLVMOrcThreadSafeModuleRef jl_get_llvm_module_impl(void *native_code) { jl_native_code_desc_t *data = (jl_native_code_desc_t*)native_code; if (data) - return data->M.get(); + return reinterpret_cast(&data->M); else return NULL; } @@ -132,16 +132,6 @@ GlobalValue* jl_get_llvm_function_impl(void *native_code, uint32_t idx) return NULL; } -extern "C" JL_DLLEXPORT -LLVMContext* jl_get_llvm_context_impl(void *native_code) -{ - jl_native_code_desc_t *data = (jl_native_code_desc_t*)native_code; - if (data) - return &data->M->getContext(); - else - return NULL; -} - static void emit_offset_table(Module &mod, const std::vector &vars, StringRef name, Type *T_psize) { @@ -256,19 +246,24 @@ static void jl_ci_cache_lookup(const jl_cgparams_t &cgparams, jl_method_instance // all reachable & inferrrable functions. The `policy` flag switches between the default // mode `0`, the extern mode `1`, and imaging mode `2`. extern "C" JL_DLLEXPORT -void *jl_create_native_impl(jl_array_t *methods, LLVMContextRef llvmctxt, const jl_cgparams_t *cgparams, int _policy) +void *jl_create_native_impl(jl_array_t *methods, LLVMOrcThreadSafeModuleRef llvmmod, const jl_cgparams_t *cgparams, int _policy) { if (cgparams == NULL) cgparams = &jl_default_cgparams; jl_native_code_desc_t *data = new jl_native_code_desc_t; - jl_codegen_params_t params; - params.params = cgparams; - std::map emitted; + orc::ThreadSafeModule backing; + if (!llvmmod) { + backing = jl_create_llvm_module("text", jl_ExecutionEngine->getContext()); + } + orc::ThreadSafeModule &clone = llvmmod ? *reinterpret_cast(llvmmod) : backing; + auto ctxt = clone.getContext(); + jl_workqueue_t emitted; jl_method_instance_t *mi = NULL; jl_code_info_t *src = NULL; JL_GC_PUSH1(&src); JL_LOCK(&jl_codegen_lock); - auto &ctxt = llvmctxt ? *unwrap(llvmctxt) : *jl_ExecutionEngine->getContext().getContext(); + jl_codegen_params_t params(ctxt); + params.params = cgparams; uint64_t compiler_start_time = 0; uint8_t measure_compile_time_enabled = jl_atomic_load_relaxed(&jl_measure_compile_time_enabled); if (measure_compile_time_enabled) @@ -277,7 +272,6 @@ void *jl_create_native_impl(jl_array_t *methods, LLVMContextRef llvmctxt, const CompilationPolicy policy = (CompilationPolicy) _policy; if (policy == CompilationPolicy::ImagingMode) imaging_mode = 1; - std::unique_ptr clone(jl_create_llvm_module("text", ctxt)); // compile all methods for the current world and type-inference world size_t compile_for[] = { jl_typeinf_world, jl_atomic_load_acquire(&jl_world_counter) }; @@ -295,7 +289,7 @@ void *jl_create_native_impl(jl_array_t *methods, LLVMContextRef llvmctxt, const jl_value_t *item = jl_array_ptr_ref(methods, i); if (jl_is_simplevector(item)) { if (worlds == 1) - jl_compile_extern_c(wrap(clone.get()), ¶ms, NULL, jl_svecref(item, 0), jl_svecref(item, 1)); + jl_compile_extern_c(reinterpret_cast(&clone), ¶ms, NULL, jl_svecref(item, 0), jl_svecref(item, 1)); continue; } mi = (jl_method_instance_t*)item; @@ -310,15 +304,18 @@ void *jl_create_native_impl(jl_array_t *methods, LLVMContextRef llvmctxt, const if (src && !emitted.count(codeinst)) { // now add it to our compilation results JL_GC_PROMISE_ROOTED(codeinst->rettype); - jl_compile_result_t result = jl_emit_code(mi, src, codeinst->rettype, params, ctxt); - if (std::get<0>(result)) - emitted[codeinst] = std::move(result); + orc::ThreadSafeModule result_m = jl_create_llvm_module(name_from_method_instance(codeinst->def), + params.tsctx, clone.getModuleUnlocked()->getDataLayout(), + Triple(clone.getModuleUnlocked()->getTargetTriple())); + jl_llvm_functions_t decls = jl_emit_code(result_m, mi, src, codeinst->rettype, params); + if (result_m) + emitted[codeinst] = {std::move(result_m), std::move(decls)}; } } } // finally, make sure all referenced methods also get compiled or fixed up - jl_compile_workqueue(emitted, params, policy, clone->getContext()); + jl_compile_workqueue(emitted, *clone.getModuleUnlocked(), params, policy); } JL_GC_POP(); @@ -333,7 +330,7 @@ void *jl_create_native_impl(jl_array_t *methods, LLVMContextRef llvmctxt, const // clones the contents of the module `m` to the shadow_output collector // while examining and recording what kind of function pointer we have for (auto &def : emitted) { - jl_merge_module(clone.get(), std::move(std::get<0>(def.second))); + jl_merge_module(clone, std::move(std::get<0>(def.second))); jl_code_instance_t *this_code = def.first; jl_llvm_functions_t decls = std::get<1>(def.second); StringRef func = decls.functionObject; @@ -347,44 +344,47 @@ void *jl_create_native_impl(jl_array_t *methods, LLVMContextRef llvmctxt, const func_id = -2; } else { - data->jl_sysimg_fvars.push_back(cast(clone->getNamedValue(func))); + //Safe b/c context is locked by params + data->jl_sysimg_fvars.push_back(cast(clone.getModuleUnlocked()->getNamedValue(func))); func_id = data->jl_sysimg_fvars.size(); } if (!cfunc.empty()) { - data->jl_sysimg_fvars.push_back(cast(clone->getNamedValue(cfunc))); + //Safe b/c context is locked by params + data->jl_sysimg_fvars.push_back(cast(clone.getModuleUnlocked()->getNamedValue(cfunc))); cfunc_id = data->jl_sysimg_fvars.size(); } data->jl_fvar_map[this_code] = std::make_tuple(func_id, cfunc_id); } if (params._shared_module) { - std::unique_ptr shared(params._shared_module); - params._shared_module = NULL; - jl_merge_module(clone.get(), std::move(shared)); + jl_merge_module(clone, std::move(params._shared_module)); } // now get references to the globals in the merged module // and set them to be internalized and initialized at startup for (auto &global : gvars) { - GlobalVariable *G = cast(clone->getNamedValue(global)); + //Safe b/c context is locked by params + GlobalVariable *G = cast(clone.getModuleUnlocked()->getNamedValue(global)); G->setInitializer(ConstantPointerNull::get(cast(G->getValueType()))); G->setLinkage(GlobalVariable::InternalLinkage); data->jl_sysimg_gvars.push_back(G); } + //Safe b/c context is locked by params #if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_) // setting the function personality enables stack unwinding and catching exceptions // so make sure everything has something set - Type *T_int32 = Type::getInt32Ty(clone->getContext()); + Type *T_int32 = Type::getInt32Ty(clone.getModuleUnlocked()->getContext()); Function *juliapersonality_func = Function::Create(FunctionType::get(T_int32, true), - Function::ExternalLinkage, "__julia_personality", clone.get()); + Function::ExternalLinkage, "__julia_personality", clone.getModuleUnlocked()); juliapersonality_func->setDLLStorageClass(GlobalValue::DLLImportStorageClass); #endif // move everything inside, now that we've merged everything // (before adding the exported headers) if (policy == CompilationPolicy::Default) { - for (GlobalObject &G : clone->global_objects()) { + //Safe b/c context is locked by params + for (GlobalObject &G : clone.getModuleUnlocked()->global_objects()) { if (!G.isDeclaration()) { G.setLinkage(Function::InternalLinkage); makeSafeName(G); @@ -441,7 +441,9 @@ void jl_dump_native_impl(void *native_code, { JL_TIMING(NATIVE_DUMP); jl_native_code_desc_t *data = (jl_native_code_desc_t*)native_code; - LLVMContext &Context = data->M->getContext(); + auto TSCtx = data->M.getContext(); + auto lock = TSCtx.getLock(); + LLVMContext &Context = *TSCtx.getContext(); // We don't want to use MCJIT's target machine because // it uses the large code model and we may potentially // want less optimizations there. @@ -508,8 +510,9 @@ void jl_dump_native_impl(void *native_code, jl_safe_printf("ERROR: target does not support generation of object files\n"); // Reset the target triple to make sure it matches the new target machine - data->M->setTargetTriple(TM->getTargetTriple().str()); - data->M->setDataLayout(create_jl_data_layout(*TM)); + auto dataM = data->M.getModuleUnlocked(); + dataM->setTargetTriple(TM->getTargetTriple().str()); + dataM->setDataLayout(jl_create_datalayout(*TM)); Type *T_size; if (sizeof(size_t) == 8) T_size = Type::getInt64Ty(Context); @@ -519,13 +522,13 @@ void jl_dump_native_impl(void *native_code, // add metadata information if (imaging_mode) { - emit_offset_table(*data->M, data->jl_sysimg_gvars, "jl_sysimg_gvars", T_psize); - emit_offset_table(*data->M, data->jl_sysimg_fvars, "jl_sysimg_fvars", T_psize); + emit_offset_table(*dataM, data->jl_sysimg_gvars, "jl_sysimg_gvars", T_psize); + emit_offset_table(*dataM, data->jl_sysimg_fvars, "jl_sysimg_fvars", T_psize); // reflect the address of the jl_RTLD_DEFAULT_handle variable // back to the caller, so that we can check for consistency issues - GlobalValue *jlRTLD_DEFAULT_var = jl_emit_RTLD_DEFAULT_var(data->M.get()); - addComdat(new GlobalVariable(*data->M, + GlobalValue *jlRTLD_DEFAULT_var = jl_emit_RTLD_DEFAULT_var(dataM); + addComdat(new GlobalVariable(*dataM, jlRTLD_DEFAULT_var->getType(), true, GlobalVariable::ExternalLinkage, @@ -546,29 +549,30 @@ void jl_dump_native_impl(void *native_code, emit_result(asm_Archive, asm_Buffer, asm_Name, outputs); }; - add_output(*data->M, "unopt.bc", "text.bc", "text.o", "text.s"); + add_output(*dataM, "unopt.bc", "text.bc", "text.o", "text.s"); - std::unique_ptr sysimage(new Module("sysimage", Context)); - sysimage->setTargetTriple(data->M->getTargetTriple()); - sysimage->setDataLayout(data->M->getDataLayout()); + orc::ThreadSafeModule sysimage(std::make_unique("sysimage", Context), TSCtx); + auto sysimageM = sysimage.getModuleUnlocked(); + sysimageM->setTargetTriple(dataM->getTargetTriple()); + sysimageM->setDataLayout(dataM->getDataLayout()); #if JL_LLVM_VERSION >= 130000 - sysimage->setStackProtectorGuard(data->M->getStackProtectorGuard()); - sysimage->setOverrideStackAlignment(data->M->getOverrideStackAlignment()); + sysimageM->setStackProtectorGuard(dataM->getStackProtectorGuard()); + sysimageM->setOverrideStackAlignment(dataM->getOverrideStackAlignment()); #endif - data->M.reset(); // free memory for data->M + data->M = orc::ThreadSafeModule(); // free memory for data->M if (sysimg_data) { Constant *data = ConstantDataArray::get(Context, ArrayRef((const unsigned char*)sysimg_data, sysimg_len)); - addComdat(new GlobalVariable(*sysimage, data->getType(), false, + addComdat(new GlobalVariable(*sysimageM, data->getType(), false, GlobalVariable::ExternalLinkage, data, "jl_system_image_data"))->setAlignment(Align(64)); Constant *len = ConstantInt::get(T_size, sysimg_len); - addComdat(new GlobalVariable(*sysimage, len->getType(), true, + addComdat(new GlobalVariable(*sysimageM, len->getType(), true, GlobalVariable::ExternalLinkage, len, "jl_system_image_size")); } - add_output(*sysimage, "data.bc", "data.bc", "data.o", "data.s"); + add_output(*sysimageM, "data.bc", "data.bc", "data.o", "data.s"); object::Archive::Kind Kind = getDefaultForHost(TheTriple); if (unopt_bc_fname) @@ -974,7 +978,7 @@ llvmGetPassPluginInfo() { // this is paired with jl_dump_function_ir, jl_dump_function_asm, jl_dump_method_asm in particular ways: // misuse will leak memory or cause read-after-free extern "C" JL_DLLEXPORT -void *jl_get_llvmf_defn_impl(jl_method_instance_t *mi, LLVMContextRef ctxt, size_t world, char getwrapper, char optimize, const jl_cgparams_t params) +void *jl_get_llvmf_defn_impl(jl_method_instance_t *mi, size_t world, char getwrapper, char optimize, const jl_cgparams_t params) { if (jl_is_method(mi->def.method) && mi->def.method->source == NULL && mi->def.method->generator == NULL) { @@ -1016,17 +1020,16 @@ void *jl_get_llvmf_defn_impl(jl_method_instance_t *mi, LLVMContextRef ctxt, size // emit this function into a new llvm module if (src && jl_is_code_info(src)) { - jl_codegen_params_t output; + JL_LOCK(&jl_codegen_lock); + jl_codegen_params_t output(jl_ExecutionEngine->getContext()); output.world = world; output.params = ¶ms; - std::unique_ptr m; - jl_llvm_functions_t decls; - JL_LOCK(&jl_codegen_lock); + orc::ThreadSafeModule m = jl_create_llvm_module(name_from_method_instance(mi), output.tsctx); uint64_t compiler_start_time = 0; uint8_t measure_compile_time_enabled = jl_atomic_load_relaxed(&jl_measure_compile_time_enabled); if (measure_compile_time_enabled) compiler_start_time = jl_hrtime(); - std::tie(m, decls) = jl_emit_code(mi, src, jlrettype, output, *unwrap(ctxt)); + auto decls = jl_emit_code(m, mi, src, jlrettype, output); Function *F = NULL; if (m) { @@ -1037,7 +1040,8 @@ void *jl_get_llvmf_defn_impl(jl_method_instance_t *mi, LLVMContextRef ctxt, size for (auto &global : output.globals) global.second->setLinkage(GlobalValue::ExternalLinkage); if (optimize) - PM->run(*m.get()); + //Safe b/c context lock is held by output + PM->run(*m.getModuleUnlocked()); const std::string *fname; if (decls.functionObject == "jl_fptr_args" || decls.functionObject == "jl_fptr_sparam") getwrapper = false; @@ -1045,15 +1049,14 @@ void *jl_get_llvmf_defn_impl(jl_method_instance_t *mi, LLVMContextRef ctxt, size fname = &decls.specFunctionObject; else fname = &decls.functionObject; - F = cast(m->getNamedValue(*fname)); - m.release(); // the return object `llvmf` will be the owning pointer + F = cast(m.getModuleUnlocked()->getNamedValue(*fname)); } JL_GC_POP(); if (measure_compile_time_enabled) jl_atomic_fetch_add_relaxed(&jl_cumulative_compile_time, (jl_hrtime() - compiler_start_time)); JL_UNLOCK(&jl_codegen_lock); // Might GC if (F) - return F; + return new jl_llvmf_dump_t{std::move(m), F}; } const char *mname = name_from_method_instance(mi); diff --git a/src/ccall.cpp b/src/ccall.cpp index 086b30d414938..f56013cbfab66 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -11,38 +11,40 @@ GlobalVariable *jl_emit_RTLD_DEFAULT_var(Module *M) // Find or create the GVs for the library and symbol lookup. // Return `runtime_lib` (whether the library name is a string) // The `lib` and `sym` GV returned may not be in the current module. -static bool runtime_sym_gvs(jl_codegen_params_t &emission_context, LLVMContext &ctxt, const char *f_lib, const char *f_name, +static bool runtime_sym_gvs(jl_codectx_t &ctx, const char *f_lib, const char *f_name, GlobalVariable *&lib, GlobalVariable *&sym) { - Module *M = emission_context.shared_module(ctxt); + auto &TSM = ctx.emission_context.shared_module(*jl_Module); + //Safe b/c emission context holds context lock + auto M = TSM.getModuleUnlocked(); bool runtime_lib = false; GlobalVariable *libptrgv; jl_codegen_params_t::SymMapGV *symMap; #ifdef _OS_WINDOWS_ if ((intptr_t)f_lib == (intptr_t)JL_EXE_LIBNAME) { libptrgv = prepare_global_in(M, jlexe_var); - symMap = &emission_context.symMapExe; + symMap = &ctx.emission_context.symMapExe; } else if ((intptr_t)f_lib == (intptr_t)JL_LIBJULIA_INTERNAL_DL_LIBNAME) { libptrgv = prepare_global_in(M, jldlli_var); - symMap = &emission_context.symMapDlli; + symMap = &ctx.emission_context.symMapDlli; } else if ((intptr_t)f_lib == (intptr_t)JL_LIBJULIA_DL_LIBNAME) { libptrgv = prepare_global_in(M, jldll_var); - symMap = &emission_context.symMapDll; + symMap = &ctx.emission_context.symMapDll; } else #endif if (f_lib == NULL) { libptrgv = jl_emit_RTLD_DEFAULT_var(M); - symMap = &emission_context.symMapDefault; + symMap = &ctx.emission_context.symMapDefault; } else { std::string name = "ccalllib_"; name += llvm::sys::path::filename(f_lib); name += std::to_string(globalUniqueGeneratedNames++); runtime_lib = true; - auto &libgv = emission_context.libMapGV[f_lib]; + auto &libgv = ctx.emission_context.libMapGV[f_lib]; if (libgv.first == NULL) { libptrgv = new GlobalVariable(*M, getInt8PtrTy(M->getContext()), false, GlobalVariable::ExternalLinkage, @@ -175,7 +177,7 @@ static Value *runtime_sym_lookup( Constant::getNullValue(T_pvoidfunc), gvname); } else { - runtime_lib = runtime_sym_gvs(ctx.emission_context, ctx.builder.getContext(), f_lib, f_name, libptrgv, llvmgv); + runtime_lib = runtime_sym_gvs(ctx, f_lib, f_name, libptrgv, llvmgv); libptrgv = prepare_global_in(jl_Module, libptrgv); } llvmgv = prepare_global_in(jl_Module, llvmgv); @@ -185,13 +187,14 @@ static Value *runtime_sym_lookup( // Emit a "PLT" entry that will be lazily initialized // when being called the first time. static GlobalVariable *emit_plt_thunk( - jl_codegen_params_t &emission_context, + jl_codectx_t &ctx, FunctionType *functype, const AttributeList &attrs, CallingConv::ID cc, const char *f_lib, const char *f_name, GlobalVariable *libptrgv, GlobalVariable *llvmgv, bool runtime_lib) { - Module *M = emission_context.shared_module(functype->getContext()); + auto &TSM = ctx.emission_context.shared_module(*jl_Module); + Module *M = TSM.getModuleUnlocked(); PointerType *funcptype = PointerType::get(functype, 0); libptrgv = prepare_global_in(M, libptrgv); llvmgv = prepare_global_in(M, llvmgv); @@ -211,7 +214,7 @@ static GlobalVariable *emit_plt_thunk( fname); BasicBlock *b0 = BasicBlock::Create(M->getContext(), "top", plt); IRBuilder<> irbuilder(b0); - Value *ptr = runtime_sym_lookup(emission_context, irbuilder, NULL, funcptype, f_lib, NULL, f_name, plt, libptrgv, + Value *ptr = runtime_sym_lookup(ctx.emission_context, irbuilder, NULL, funcptype, f_lib, NULL, f_name, plt, libptrgv, llvmgv, runtime_lib); StoreInst *store = irbuilder.CreateAlignedStore(irbuilder.CreateBitCast(ptr, T_pvoidfunc), got, Align(sizeof(void*))); store->setAtomic(AtomicOrdering::Release); @@ -266,14 +269,14 @@ static Value *emit_plt( assert(!functype->isVarArg()); GlobalVariable *libptrgv; GlobalVariable *llvmgv; - bool runtime_lib = runtime_sym_gvs(ctx.emission_context, ctx.builder.getContext(), f_lib, f_name, libptrgv, llvmgv); + bool runtime_lib = runtime_sym_gvs(ctx, f_lib, f_name, libptrgv, llvmgv); PointerType *funcptype = PointerType::get(functype, 0); auto &pltMap = ctx.emission_context.allPltMap[attrs]; auto key = std::make_tuple(llvmgv, functype, cc); GlobalVariable *&sharedgot = pltMap[key]; if (!sharedgot) { - sharedgot = emit_plt_thunk(ctx.emission_context, + sharedgot = emit_plt_thunk(ctx, functype, attrs, cc, f_lib, f_name, libptrgv, llvmgv, runtime_lib); } GlobalVariable *got = prepare_global_in(jl_Module, sharedgot); @@ -921,7 +924,7 @@ static jl_cgval_t emit_llvmcall(jl_codectx_t &ctx, jl_value_t **args, size_t nar // save the module to be linked later. // we cannot do this right now, because linking mutates the destination module, // which might invalidate LLVM values cached in cgval_t's (specifically constant arrays) - ctx.llvmcall_modules.push_back(std::move(Mod)); + ctx.llvmcall_modules.push_back(orc::ThreadSafeModule(std::move(Mod), ctx.emission_context.tsctx)); JL_GC_POP(); diff --git a/src/codegen-stubs.c b/src/codegen-stubs.c index 97f2b454563eb..bf220a0456066 100644 --- a/src/codegen-stubs.c +++ b/src/codegen-stubs.c @@ -19,7 +19,7 @@ JL_DLLEXPORT void jl_extern_c_fallback(jl_function_t *f, jl_value_t *rt, jl_valu JL_DLLEXPORT jl_value_t *jl_dump_method_asm_fallback(jl_method_instance_t *linfo, size_t world, char raw_mc, char getwrapper, const char* asm_variant, const char *debuginfo, char binary) UNAVAILABLE JL_DLLEXPORT jl_value_t *jl_dump_function_ir_fallback(void *f, char strip_ir_metadata, char dump_module, const char *debuginfo) UNAVAILABLE -JL_DLLEXPORT void *jl_get_llvmf_defn_fallback(jl_method_instance_t *linfo, LLVMContextRef ctxt, size_t world, char getwrapper, char optimize, const jl_cgparams_t params) UNAVAILABLE +JL_DLLEXPORT void *jl_get_llvmf_defn_fallback(jl_method_instance_t *linfo, size_t world, char getwrapper, char optimize, const jl_cgparams_t params) UNAVAILABLE JL_DLLEXPORT void *jl_LLVMCreateDisasm_fallback(const char *TripleName, void *DisInfo, int TagType, void *GetOpInfo, void *SymbolLookUp) UNAVAILABLE JL_DLLEXPORT size_t jl_LLVMDisasmInstruction_fallback(void *DC, uint8_t *Bytes, uint64_t BytesSize, uint64_t PC, char *OutString, size_t OutStringSize) UNAVAILABLE @@ -52,7 +52,7 @@ JL_DLLEXPORT uint32_t jl_get_LLVM_VERSION_fallback(void) return 0; } -JL_DLLEXPORT int jl_compile_extern_c_fallback(LLVMModuleRef llvmmod, void *params, void *sysimg, jl_value_t *declrt, jl_value_t *sigt) +JL_DLLEXPORT int jl_compile_extern_c_fallback(LLVMOrcThreadSafeModuleRef llvmmod, void *params, void *sysimg, jl_value_t *declrt, jl_value_t *sigt) { return 0; } @@ -74,7 +74,7 @@ JL_DLLEXPORT void jl_unlock_profile_fallback(void) { } -JL_DLLEXPORT void *jl_create_native_fallback(jl_array_t *methods, LLVMContextRef llvmctxt, const jl_cgparams_t *cgparams, int _policy) UNAVAILABLE +JL_DLLEXPORT void *jl_create_native_fallback(jl_array_t *methods, LLVMOrcThreadSafeModuleRef llvmctxt, const jl_cgparams_t *cgparams, int _policy) UNAVAILABLE JL_DLLEXPORT void jl_dump_compiles_fallback(void *s) { @@ -92,16 +92,13 @@ JL_DLLEXPORT jl_value_t *jl_dump_fptr_asm_fallback(uint64_t fptr, char raw_mc, c JL_DLLEXPORT jl_value_t *jl_dump_function_asm_fallback(void *F, char raw_mc, const char* asm_variant, const char *debuginfo, char binary) UNAVAILABLE -JL_DLLEXPORT LLVMContextRef jl_get_ee_context_fallback(void) UNAVAILABLE - JL_DLLEXPORT void jl_get_function_id_fallback(void *native_code, jl_code_instance_t *ncode, int32_t *func_idx, int32_t *specfunc_idx) UNAVAILABLE -JL_DLLEXPORT void *jl_get_llvm_context_fallback(void *native_code) UNAVAILABLE JL_DLLEXPORT void *jl_get_llvm_function_fallback(void *native_code, uint32_t idx) UNAVAILABLE -JL_DLLEXPORT void *jl_get_llvm_module_fallback(void *native_code) UNAVAILABLE +JL_DLLEXPORT LLVMOrcThreadSafeModuleRef jl_get_llvm_module_fallback(void *native_code) UNAVAILABLE JL_DLLEXPORT void *jl_type_to_llvm_fallback(jl_value_t *jt, LLVMContextRef llvmctxt, bool_t *isboxed) UNAVAILABLE diff --git a/src/codegen.cpp b/src/codegen.cpp index ab652f72c73a1..4cb72567df63b 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1309,7 +1309,7 @@ class jl_codectx_t { std::vector SAvalues; std::vector> PhiNodes; std::vector ssavalue_assigned; - std::vector> oc_modules; + std::vector oc_modules; jl_module_t *module = NULL; jl_typecache_t type_cache; jl_tbaacache_t tbaa_cache; @@ -1340,7 +1340,7 @@ class jl_codectx_t { bool use_cache = false; const jl_cgparams_t *params = NULL; - std::vector> llvmcall_modules; + std::vector llvmcall_modules; jl_codectx_t(LLVMContext &llvmctx, jl_codegen_params_t ¶ms) : builder(llvmctx), @@ -1953,9 +1953,11 @@ static jl_cgval_t convert_julia_type(jl_codectx_t &ctx, const jl_cgval_t &v, jl_ return jl_cgval_t(v, typ, new_tindex); } -Module *_jl_create_llvm_module(StringRef name, LLVMContext &context, const jl_cgparams_t *params, const DataLayout &DL, const Triple &triple) +orc::ThreadSafeModule jl_create_llvm_module(StringRef name, orc::ThreadSafeContext context, const DataLayout &DL, const Triple &triple) { - Module *m = new Module(name, context); + auto lock = context.getLock(); + Module *m = new Module(name, *context.getContext()); + orc::ThreadSafeModule TSM(std::unique_ptr(m), std::move(context)); // Some linkers (*cough* OS X) don't understand DWARF v4, so we use v2 in // imaging mode. The structure of v4 is slightly nicer for debugging JIT // code. @@ -1982,12 +1984,7 @@ Module *_jl_create_llvm_module(StringRef name, LLVMContext &context, const jl_cg #if defined(JL_DEBUG_BUILD) && JL_LLVM_VERSION >= 130000 m->setStackProtectorGuard("global"); #endif - return m; -} - -Module *jl_create_llvm_module(StringRef name, LLVMContext &ctx, const DataLayout *DL, const Triple *triple) -{ - return _jl_create_llvm_module(name, ctx, &jl_default_cgparams, DL ? *DL : jl_ExecutionEngine->getDataLayout(), triple ? *triple : jl_ExecutionEngine->getTargetTriple()); + return TSM; } static void jl_init_function(Function *F) @@ -2886,13 +2883,13 @@ static bool emit_f_opfield(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, return false; } -static std::pair, jl_llvm_functions_t> +static jl_llvm_functions_t emit_function( + orc::ThreadSafeModule &TSM, jl_method_instance_t *lam, jl_code_info_t *src, jl_value_t *jlrettype, - jl_codegen_params_t ¶ms, - LLVMContext &ctxt); + jl_codegen_params_t ¶ms); static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, const jl_cgval_t *argv, size_t nargs, jl_value_t *rt, @@ -4724,10 +4721,10 @@ static std::pair get_oc_function(jl_codectx_t &ctx, jl_met ir = jl_uncompress_ir(closure_method, ci, (jl_array_t*)ci->inferred); // TODO: Emit this inline and outline it late using LLVM's coroutine support. - std::unique_ptr closure_m; - jl_llvm_functions_t closure_decls; - std::tie(closure_m, closure_decls) = emit_function(mi, ir, rettype, ctx.emission_context, - ctx.builder.getContext()); + orc::ThreadSafeModule closure_m = jl_create_llvm_module( + name_from_method_instance(mi), ctx.emission_context.tsctx, + jl_Module->getDataLayout(), Triple(jl_Module->getTargetTriple())); + jl_llvm_functions_t closure_decls = emit_function(closure_m, mi, ir, rettype, ctx.emission_context); assert(closure_decls.functionObject != "jl_fptr_sparam"); bool isspecsig = closure_decls.functionObject != "jl_fptr_args"; @@ -4748,7 +4745,8 @@ static std::pair get_oc_function(jl_codectx_t &ctx, jl_met if (!isspecsig) { specF = F; } else { - specF = closure_m->getFunction(closure_decls.specFunctionObject); + //emission context holds context lock so can get module + specF = closure_m.getModuleUnlocked()->getFunction(closure_decls.specFunctionObject); if (specF) { jl_returninfo_t returninfo = get_specsig_function(ctx, jl_Module, closure_decls.specFunctionObject, sigtype, rettype, true); @@ -5431,7 +5429,7 @@ static Function* gen_cfun_wrapper( std::string funcName; raw_string_ostream(funcName) << "jlcapi_" << name << "_" << globalUniqueGeneratedNames++; - Module *M = into; + Module *M = into; // Safe because ctx lock is held by params AttributeList attributes = sig.attributes; FunctionType *functype; if (nest) { @@ -6098,7 +6096,7 @@ static jl_cgval_t emit_cfunction(jl_codectx_t &ctx, jl_value_t *output_type, con // do codegen to create a C-callable alias/wrapper, or if sysimg_handle is set, // restore one from a loaded system image. -const char *jl_generate_ccallable(void *llvmmod, void *sysimg_handle, jl_value_t *declrt, jl_value_t *sigt, jl_codegen_params_t ¶ms, LLVMContext &ctxt) +const char *jl_generate_ccallable(LLVMOrcThreadSafeModuleRef llvmmod, void *sysimg_handle, jl_value_t *declrt, jl_value_t *sigt, jl_codegen_params_t ¶ms) { jl_datatype_t *ft = (jl_datatype_t*)jl_tparam0(sigt); jl_value_t *ff = ft->instance; @@ -6110,7 +6108,7 @@ const char *jl_generate_ccallable(void *llvmmod, void *sysimg_handle, jl_value_t crt = (jl_value_t*)jl_any_type; } bool toboxed; - Type *lcrt = _julia_struct_to_llvm(¶ms, ctxt, crt, &toboxed); + Type *lcrt = _julia_struct_to_llvm(¶ms, *params.tsctx.getContext(), crt, &toboxed); if (toboxed) lcrt = JuliaType::get_prjlvalue_ty(lcrt->getContext()); size_t nargs = jl_nparams(sigt)-1; @@ -6137,7 +6135,8 @@ const char *jl_generate_ccallable(void *llvmmod, void *sysimg_handle, jl_value_t } else { jl_method_instance_t *lam = jl_get_specialization1((jl_tupletype_t*)sigt, world, &min_valid, &max_valid, 0); - gen_cfun_wrapper((Module*)llvmmod, params, sig, ff, name, declrt, lam, NULL, NULL, NULL); + //Safe b/c params holds context lock + gen_cfun_wrapper(reinterpret_cast(llvmmod)->getModuleUnlocked(), params, sig, ff, name, declrt, lam, NULL, NULL, NULL); } JL_GC_POP(); return name; @@ -6433,17 +6432,17 @@ static jl_datatype_t *compute_va_type(jl_method_instance_t *lam, size_t nreq) } // Compile to LLVM IR, using a specialized signature if applicable. -static std::pair, jl_llvm_functions_t> +static jl_llvm_functions_t emit_function( + orc::ThreadSafeModule &TSM, jl_method_instance_t *lam, jl_code_info_t *src, jl_value_t *jlrettype, - jl_codegen_params_t ¶ms, - LLVMContext &ctxt) + jl_codegen_params_t ¶ms) { // step 1. unpack AST and allocate codegen context for this function jl_llvm_functions_t declarations; - jl_codectx_t ctx(ctxt, params); + jl_codectx_t ctx(*params.tsctx.getContext(), params); jl_datatype_t *vatyp = NULL; JL_GC_PUSH3(&ctx.code, &ctx.roots, &vatyp); ctx.code = src->code; @@ -6452,7 +6451,7 @@ static std::pair, jl_llvm_functions_t> bool toplevel = false; ctx.module = jl_is_method(lam->def.method) ? lam->def.method->module : lam->def.module; ctx.linfo = lam; - ctx.name = name_from_method_instance(lam); + ctx.name = TSM.getModuleUnlocked()->getModuleIdentifier().data(); size_t nreq = 0; int va = 0; if (jl_is_method(lam->def.method)) { @@ -6593,7 +6592,8 @@ static std::pair, jl_llvm_functions_t> declarations.specFunctionObject = funcName.str(); // allocate Function declarations and wrapper objects - Module *M = _jl_create_llvm_module(ctx.name, ctx.builder.getContext(), ctx.params, jl_ExecutionEngine->getDataLayout(), jl_ExecutionEngine->getTargetTriple()); + //Safe because params holds ctx lock + Module *M = TSM.getModuleUnlocked(); jl_debugcache_t debuginfo; debuginfo.initialize(M); jl_returninfo_t returninfo = {}; @@ -7883,31 +7883,33 @@ static std::pair, jl_llvm_functions_t> // link the dependent llvmcall modules, but switch their function's linkage to internal // so that they don't conflict when they show up in the execution engine. - for (auto &Mod : ctx.llvmcall_modules) { + for (auto &TSMod : ctx.llvmcall_modules) { SmallVector Exports; - for (const auto &F: Mod->functions()) + TSMod.withModuleDo([&](Module &Mod) { //TODO fix indentation after review + for (const auto &F: Mod.functions()) if (!F.isDeclaration()) Exports.push_back(F.getName().str()); - if (Linker::linkModules(*jl_Module, std::move(Mod))) { - jl_error("Failed to link LLVM bitcode"); - } + }); + jl_merge_module(TSM, std::move(TSMod)); for (auto FN: Exports) jl_Module->getFunction(FN)->setLinkage(GlobalVariable::InternalLinkage); } // link in opaque closure modules - for (auto &Mod : ctx.oc_modules) { + for (auto &TSMod : ctx.oc_modules) { SmallVector Exports; - for (const auto &F: Mod->functions()) + TSMod.withModuleDo([&](Module &Mod) { //TODO fix indentation after review + for (const auto &F: Mod.functions()) if (!F.isDeclaration()) Exports.push_back(F.getName().str()); - jl_merge_module(jl_Module, std::move(Mod)); + }); + jl_merge_module(TSM, std::move(TSMod)); for (auto FN: Exports) jl_Module->getFunction(FN)->setLinkage(GlobalVariable::InternalLinkage); } JL_GC_POP(); - return std::make_pair(std::unique_ptr(M), declarations); + return declarations; } // --- entry point --- @@ -7915,22 +7917,21 @@ static std::pair, jl_llvm_functions_t> void jl_add_code_in_flight(StringRef name, jl_code_instance_t *codeinst, const DataLayout &DL); JL_GCC_IGNORE_START("-Wclobbered") -jl_compile_result_t jl_emit_code( +jl_llvm_functions_t jl_emit_code( + orc::ThreadSafeModule &m, jl_method_instance_t *li, jl_code_info_t *src, jl_value_t *jlrettype, - jl_codegen_params_t ¶ms, - LLVMContext &context) + jl_codegen_params_t ¶ms) { JL_TIMING(CODEGEN); // caller must hold codegen_lock jl_llvm_functions_t decls = {}; - std::unique_ptr m; assert((params.params == &jl_default_cgparams /* fast path */ || !params.cache || compare_cgparams(params.params, &jl_default_cgparams)) && "functions compiled with custom codegen params must not be cached"); JL_TRY { - std::tie(m, decls) = emit_function(li, src, jlrettype, params, context); + decls = emit_function(m, li, src, jlrettype, params); if (dump_emitted_mi_name_stream != NULL) { jl_printf(dump_emitted_mi_name_stream, "%s\t", decls.specFunctionObject.c_str()); // NOTE: We print the Type Tuple without surrounding quotes, because the quotes @@ -7945,24 +7946,24 @@ jl_compile_result_t jl_emit_code( JL_CATCH { // Something failed! This is very, very bad. // Try to pretend that it isn't and attempt to recover. - m.reset(); + const char *mname = m.getModuleUnlocked()->getModuleIdentifier().data(); + m = orc::ThreadSafeModule(); decls.functionObject = ""; decls.specFunctionObject = ""; - const char *mname = name_from_method_instance(li); jl_printf((JL_STREAM*)STDERR_FILENO, "Internal error: encountered unexpected error during compilation of %s:\n", mname); jl_static_show((JL_STREAM*)STDERR_FILENO, jl_current_exception()); jl_printf((JL_STREAM*)STDERR_FILENO, "\n"); jlbacktrace(); // written to STDERR_FILENO } - return std::make_tuple(std::move(m), decls); + return decls; } -jl_compile_result_t jl_emit_codeinst( +jl_llvm_functions_t jl_emit_codeinst( + orc::ThreadSafeModule &m, jl_code_instance_t *codeinst, jl_code_info_t *src, - jl_codegen_params_t ¶ms, - LLVMContext &context) + jl_codegen_params_t ¶ms) { JL_TIMING(CODEGEN); JL_GC_PUSH1(&src); @@ -7973,22 +7974,22 @@ jl_compile_result_t jl_emit_codeinst( src = jl_uncompress_ir(def, codeinst, (jl_array_t*)src); if (!src || !jl_is_code_info(src)) { JL_GC_POP(); - return jl_compile_result_t(); // failed + m = orc::ThreadSafeModule(); + return jl_llvm_functions_t(); // failed } } - jl_compile_result_t result = jl_emit_code(codeinst->def, src, codeinst->rettype, params, context); + jl_llvm_functions_t decls = jl_emit_code(m, codeinst->def, src, codeinst->rettype, params); - const jl_llvm_functions_t &decls = std::get<1>(result); const std::string &specf = decls.specFunctionObject; const std::string &f = decls.functionObject; if (params.cache && !f.empty()) { - const Module *m = std::get<0>(result).get(); // Prepare debug info to receive this function // record that this function name came from this linfo, // so we can build a reverse mapping for debug-info. bool toplevel = !jl_is_method(codeinst->def->def.method); if (!toplevel) { - const DataLayout &DL = m->getDataLayout(); + //Safe b/c params holds context lock + const DataLayout &DL = m.getModuleUnlocked()->getDataLayout(); // but don't remember toplevel thunks because // they may not be rooted in the gc for the life of the program, // and the runtime doesn't notify us when the code becomes unreachable :( @@ -8032,13 +8033,14 @@ jl_compile_result_t jl_emit_codeinst( } } JL_GC_POP(); - return result; + return decls; } void jl_compile_workqueue( - std::map &emitted, - jl_codegen_params_t ¶ms, CompilationPolicy policy, LLVMContext &context) + jl_workqueue_t &emitted, + Module &original, + jl_codegen_params_t ¶ms, CompilationPolicy policy) { JL_TIMING(CODEGEN); jl_code_info_t *src = NULL; @@ -8068,7 +8070,7 @@ void jl_compile_workqueue( } } else { - jl_compile_result_t &result = emitted[codeinst]; + auto &result = emitted[codeinst]; jl_llvm_functions_t *decls = NULL; if (std::get<0>(result)) { decls = &std::get<1>(result); @@ -8079,11 +8081,20 @@ void jl_compile_workqueue( if (policy != CompilationPolicy::Default && codeinst->inferred && codeinst->inferred == jl_nothing) { src = jl_type_infer(codeinst->def, jl_atomic_load_acquire(&jl_world_counter), 0); - if (src) - result = jl_emit_code(codeinst->def, src, src->rettype, params, context); + if (src) { + orc::ThreadSafeModule result_m = + jl_create_llvm_module(name_from_method_instance(codeinst->def), + params.tsctx, original.getDataLayout(), Triple(original.getTargetTriple())); + result.second = jl_emit_code(result_m, codeinst->def, src, src->rettype, params); + result.first = std::move(result_m); + } } else { - result = jl_emit_codeinst(codeinst, NULL, params, context); + orc::ThreadSafeModule result_m = + jl_create_llvm_module(name_from_method_instance(codeinst->def), + params.tsctx, original.getDataLayout(), Triple(original.getTargetTriple())); + result.second = jl_emit_codeinst(result_m, codeinst, NULL, params); + result.first = std::move(result_m); } if (std::get<0>(result)) decls = &std::get<1>(result); diff --git a/src/disasm.cpp b/src/disasm.cpp index 0ae3e29eb1699..0946b5b9734eb 100644 --- a/src/disasm.cpp +++ b/src/disasm.cpp @@ -493,7 +493,8 @@ jl_value_t *jl_dump_function_ir_impl(void *f, char strip_ir_metadata, char dump_ raw_string_ostream stream(code); { - Function *llvmf = dyn_cast_or_null((Function*)f); + std::unique_ptr dump(static_cast(f)); + Function *llvmf = dump->F; if (!llvmf || (!llvmf->isDeclaration() && !llvmf->getParent())) jl_error("jl_dump_function_ir: Expected Function* in a temporary Module"); @@ -505,21 +506,21 @@ jl_value_t *jl_dump_function_ir_impl(void *f, char strip_ir_metadata, char dump_ delete llvmf; } else { - Module *m = llvmf->getParent(); + dump->TSM.withModuleDo([&](Module &m) { if (strip_ir_metadata) { std::string llvmfn(llvmf->getName()); - jl_strip_llvm_addrspaces(m); - jl_strip_llvm_debug(m, true, &AAW); + jl_strip_llvm_addrspaces(&m); + jl_strip_llvm_debug(&m, true, &AAW); // rewriting the function type creates a new function, so look it up again - llvmf = m->getFunction(llvmfn); + llvmf = m.getFunction(llvmfn); } if (dump_module) { - m->print(stream, &AAW); + m.print(stream, &AAW); } else { llvmf->print(stream, &AAW); } - delete m; + }); } JL_UNLOCK(&jl_codegen_lock); // Might GC } @@ -1193,14 +1194,16 @@ jl_value_t *jl_dump_function_asm_impl(void *F, char raw_mc, const char* asm_vari // precise printing via IR assembler SmallVector ObjBufferSV; { // scope block - Function *f = (Function*)F; + std::unique_ptr dump(static_cast(F)); + Function *f = dump->F; llvm::raw_svector_ostream asmfile(ObjBufferSV); assert(!f->isDeclaration()); - std::unique_ptr m(f->getParent()); - for (auto &f2 : m->functions()) { + dump->TSM.withModuleDo([&](Module &m) {//TODO fix indentation + for (auto &f2 : m.functions()) { if (f != &f2 && !f->isDeclaration()) f2.deleteBody(); } + }); LLVMTargetMachine *TM = static_cast(&jl_ExecutionEngine->getTargetMachine()); legacy::PassManager PM; addTargetPasses(&PM, TM); @@ -1208,7 +1211,7 @@ jl_value_t *jl_dump_function_asm_impl(void *F, char raw_mc, const char* asm_vari raw_svector_ostream obj_OS(ObjBufferSV); if (TM->addPassesToEmitFile(PM, obj_OS, nullptr, CGFT_ObjectFile, false, nullptr)) return jl_an_empty_string; - PM.run(*m); + dump->TSM.withModuleDo([&](Module &m) { PM.run(m); }); } else { MCContext *Context = addPassesToGenerateCode(TM, PM); @@ -1247,7 +1250,7 @@ jl_value_t *jl_dump_function_asm_impl(void *F, char raw_mc, const char* asm_vari return jl_an_empty_string; PM.add(Printer.release()); PM.add(createFreeMachineFunctionPass()); - PM.run(*m); + dump->TSM.withModuleDo([&](Module &m){ PM.run(m); }); } } return jl_pchar_to_string(ObjBufferSV.data(), ObjBufferSV.size()); diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 486b2fd9680aa..ae4db5b36b67c 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -67,7 +67,7 @@ void jl_dump_llvm_opt_impl(void *s) dump_llvm_opt_stream = (JL_STREAM*)s; } -static void jl_add_to_ee(std::unique_ptr &M, StringMap*> &NewExports); +static void jl_add_to_ee(orc::ThreadSafeModule &M, StringMap &NewExports); static void jl_decorate_module(Module &M); static uint64_t getAddressForFunction(StringRef fname); @@ -103,7 +103,7 @@ static jl_callptr_t _jl_compile_codeinst( jl_code_instance_t *codeinst, jl_code_info_t *src, size_t world, - LLVMContext &context) + orc::ThreadSafeContext context) { // caller must hold codegen_lock // and have disabled finalizers @@ -118,28 +118,35 @@ static jl_callptr_t _jl_compile_codeinst( jl_callptr_t fptr = NULL; // emit the code in LLVM IR form - jl_codegen_params_t params; + jl_codegen_params_t params(std::move(context)); // Locks the context params.cache = true; params.world = world; - std::map emitted; + jl_workqueue_t emitted; { - jl_compile_result_t result = jl_emit_codeinst(codeinst, src, params, context); - if (std::get<0>(result)) - emitted[codeinst] = std::move(result); - jl_compile_workqueue(emitted, params, CompilationPolicy::Default, context); + orc::ThreadSafeModule result_m = + jl_create_llvm_module(name_from_method_instance(codeinst->def), params.tsctx); + jl_llvm_functions_t decls = jl_emit_codeinst(result_m, codeinst, src, params); + if (result_m) + emitted[codeinst] = {std::move(result_m), std::move(decls)}; + { + auto temp_module = jl_create_llvm_module(name_from_method_instance(codeinst->def), params.tsctx); + jl_compile_workqueue(emitted, *temp_module.getModuleUnlocked(), params, CompilationPolicy::Default); + } if (params._shared_module) - jl_ExecutionEngine->addModule(std::unique_ptr(params._shared_module)); - StringMap*> NewExports; + jl_ExecutionEngine->addModule(std::move(params._shared_module)); + StringMap NewExports; StringMap NewGlobals; for (auto &global : params.globals) { NewGlobals[global.second->getName()] = global.first; } for (auto &def : emitted) { - std::unique_ptr &M = std::get<0>(def.second); + orc::ThreadSafeModule &TSM = std::get<0>(def.second); + //The underlying context object is still locked because params is not destroyed yet + auto M = TSM.getModuleUnlocked(); for (auto &F : M->global_objects()) { if (!F.isDeclaration() && F.getLinkage() == GlobalValue::ExternalLinkage) { - NewExports[F.getName()] = &M; + NewExports[F.getName()] = &TSM; } } // Let's link all globals here also (for now) @@ -152,7 +159,7 @@ static jl_callptr_t _jl_compile_codeinst( } for (auto &def : emitted) { // Add the results to the execution engine now - std::unique_ptr &M = std::get<0>(def.second); + orc::ThreadSafeModule &M = std::get<0>(def.second); jl_add_to_ee(M, NewExports); } } @@ -207,25 +214,28 @@ static jl_callptr_t _jl_compile_codeinst( return fptr; } -const char *jl_generate_ccallable(void *llvmmod, void *sysimg_handle, jl_value_t *declrt, jl_value_t *sigt, jl_codegen_params_t ¶ms, LLVMContext &ctxt); +const char *jl_generate_ccallable(LLVMOrcThreadSafeModuleRef llvmmod, void *sysimg_handle, jl_value_t *declrt, jl_value_t *sigt, jl_codegen_params_t ¶ms); // compile a C-callable alias extern "C" JL_DLLEXPORT -int jl_compile_extern_c_impl(LLVMModuleRef llvmmod, void *p, void *sysimg, jl_value_t *declrt, jl_value_t *sigt) +int jl_compile_extern_c_impl(LLVMOrcThreadSafeModuleRef llvmmod, void *p, void *sysimg, jl_value_t *declrt, jl_value_t *sigt) { JL_LOCK(&jl_codegen_lock); uint64_t compiler_start_time = 0; uint8_t measure_compile_time_enabled = jl_atomic_load_relaxed(&jl_measure_compile_time_enabled); if (measure_compile_time_enabled) compiler_start_time = jl_hrtime(); - jl_codegen_params_t params; + auto into = reinterpret_cast(llvmmod); + orc::ThreadSafeModule backing; + if (into == NULL) { + backing = jl_create_llvm_module("cextern", p ? ((jl_codegen_params_t*)p)->tsctx : jl_ExecutionEngine->getContext()); + into = &backing; + } + jl_codegen_params_t params(into->getContext()); jl_codegen_params_t *pparams = (jl_codegen_params_t*)p; if (pparams == NULL) pparams = ¶ms; - Module *into = unwrap(llvmmod); - if (into == NULL) - into = jl_create_llvm_module("cextern", *jl_ExecutionEngine->getContext().getContext()); - const char *name = jl_generate_ccallable(into, sysimg, declrt, sigt, *pparams, into->getContext()); + const char *name = jl_generate_ccallable(reinterpret_cast(into), sysimg, declrt, sigt, *pparams); bool success = true; if (!sysimg) { if (jl_ExecutionEngine->getGlobalValueAddress(name)) { @@ -235,10 +245,10 @@ int jl_compile_extern_c_impl(LLVMModuleRef llvmmod, void *p, void *sysimg, jl_va jl_jit_globals(params.globals); assert(params.workqueue.empty()); if (params._shared_module) - jl_ExecutionEngine->addModule(std::unique_ptr(params._shared_module)); + jl_ExecutionEngine->addModule(std::move(params._shared_module)); } if (success && llvmmod == NULL) - jl_ExecutionEngine->addModule(std::unique_ptr(into)); + jl_ExecutionEngine->addModule(std::move(*into)); } if (jl_codegen_lock.count == 1 && measure_compile_time_enabled) jl_atomic_fetch_add_relaxed(&jl_cumulative_compile_time, (jl_hrtime() - compiler_start_time)); @@ -296,7 +306,7 @@ extern "C" JL_DLLEXPORT jl_code_instance_t *jl_generate_fptr_impl(jl_method_instance_t *mi JL_PROPAGATES_ROOT, size_t world) { JL_LOCK(&jl_codegen_lock); // also disables finalizers, to prevent any unexpected recursion - auto &context = *jl_ExecutionEngine->getContext().getContext(); + auto &context = jl_ExecutionEngine->getContext(); uint64_t compiler_start_time = 0; uint8_t measure_compile_time_enabled = jl_atomic_load_relaxed(&jl_measure_compile_time_enabled); if (measure_compile_time_enabled) @@ -353,7 +363,7 @@ void jl_generate_fptr_for_unspecialized_impl(jl_code_instance_t *unspec) return; } JL_LOCK(&jl_codegen_lock); - auto &context = *jl_ExecutionEngine->getContext().getContext(); + auto &context = jl_ExecutionEngine->getContext(); uint64_t compiler_start_time = 0; uint8_t measure_compile_time_enabled = jl_atomic_load_relaxed(&jl_measure_compile_time_enabled); if (measure_compile_time_enabled) @@ -407,7 +417,7 @@ jl_value_t *jl_dump_method_asm_impl(jl_method_instance_t *mi, size_t world, // (using sentinel value `1` instead) // so create an exception here so we can print pretty our lies JL_LOCK(&jl_codegen_lock); // also disables finalizers, to prevent any unexpected recursion - auto &context = *jl_ExecutionEngine->getContext().getContext(); + auto &context = jl_ExecutionEngine->getContext(); uint64_t compiler_start_time = 0; uint8_t measure_compile_time_enabled = jl_atomic_load_relaxed(&jl_measure_compile_time_enabled); if (measure_compile_time_enabled) @@ -444,8 +454,7 @@ jl_value_t *jl_dump_method_asm_impl(jl_method_instance_t *mi, size_t world, } // whatever, that didn't work - use the assembler output instead - // just make a new context for this one operation - void *F = jl_get_llvmf_defn(mi, wrap(jl_ExecutionEngine->getContext().getContext()), world, getwrapper, true, jl_default_cgparams); + void *F = jl_get_llvmf_defn(mi, world, getwrapper, true, jl_default_cgparams); if (!F) return jl_an_empty_string; return jl_dump_function_asm(F, raw_mc, asm_variant, debuginfo, binary); @@ -893,7 +902,7 @@ namespace { } } -llvm::DataLayout create_jl_data_layout(TargetMachine &TM) { +llvm::DataLayout jl_create_datalayout(TargetMachine &TM) { // Mark our address spaces as non-integral auto jl_data_layout = TM.createDataLayout(); jl_data_layout.reset(jl_data_layout.getStringRepresentation() + "-ni:10:11:12:13"); @@ -902,7 +911,7 @@ llvm::DataLayout create_jl_data_layout(TargetMachine &TM) { JuliaOJIT::JuliaOJIT(LLVMContext *LLVMCtx) : TM(createTargetMachine()), - DL(create_jl_data_layout(*TM)), + DL(jl_create_datalayout(*TM)), TMs{ cantFail(createJTMBFromTM(*TM, 0).createTargetMachine()), cantFail(createJTMBFromTM(*TM, 1).createTargetMachine()), @@ -1016,39 +1025,41 @@ void JuliaOJIT::addGlobalMapping(StringRef Name, uint64_t Addr) cantFail(JD.define(orc::absoluteSymbols({{ES.intern(MangleName), JITEvaluatedSymbol::fromPointer((void*)Addr)}}))); } -void JuliaOJIT::addModule(std::unique_ptr M) +void JuliaOJIT::addModule(orc::ThreadSafeModule TSM) { JL_TIMING(LLVM_MODULE_FINISH); - jl_decorate_module(*M); - shareStrings(*M); std::vector NewExports; - for (auto &F : M->global_values()) { - if (!F.isDeclaration() && F.getLinkage() == GlobalValue::ExternalLinkage) { - NewExports.push_back(getMangledName(F.getName())); + TSM.withModuleDo([&](Module &M) { + jl_decorate_module(M); + shareStrings(M); + for (auto &F : M.global_values()) { + if (!F.isDeclaration() && F.getLinkage() == GlobalValue::ExternalLinkage) { + NewExports.push_back(getMangledName(F.getName())); + } } - } #if !defined(JL_NDEBUG) && !defined(JL_USE_JITLINK) - // validate the relocations for M (not implemented for the JITLink memory manager yet) - for (Module::global_object_iterator I = M->global_objects().begin(), E = M->global_objects().end(); I != E; ) { - GlobalObject *F = &*I; - ++I; - if (F->isDeclaration()) { - if (F->use_empty()) - F->eraseFromParent(); - else if (!((isa(F) && isIntrinsicFunction(cast(F))) || - findUnmangledSymbol(F->getName()) || - SectionMemoryManager::getSymbolAddressInProcess( - getMangledName(F->getName())))) { - llvm::errs() << "FATAL ERROR: " - << "Symbol \"" << F->getName().str() << "\"" - << "not found"; - abort(); + // validate the relocations for M (not implemented for the JITLink memory manager yet) + for (Module::global_object_iterator I = M.global_objects().begin(), E = M.global_objects().end(); I != E; ) { + GlobalObject *F = &*I; + ++I; + if (F->isDeclaration()) { + if (F->use_empty()) + F->eraseFromParent(); + else if (!((isa(F) && isIntrinsicFunction(cast(F))) || + findUnmangledSymbol(F->getName()) || + SectionMemoryManager::getSymbolAddressInProcess( + getMangledName(F->getName())))) { + llvm::errs() << "FATAL ERROR: " + << "Symbol \"" << F->getName().str() << "\"" + << "not found"; + abort(); + } } } - } #endif + }); // TODO: what is the performance characteristics of this? - cantFail(OptSelLayer.add(JD, orc::ThreadSafeModule(std::move(M), TSCtx))); + cantFail(OptSelLayer.add(JD, std::move(TSM))); // force eager compilation (for now), due to memory management specifics // (can't handle compilation recursion) for (auto Name : NewExports) @@ -1207,12 +1218,19 @@ JuliaOJIT *jl_ExecutionEngine; // including the DataLayout and ModuleFlags (for example) // and that there is no module-level assembly // Comdat is also removed, since the JIT doesn't need it -void jl_merge_module(Module *dest, std::unique_ptr src) +void jl_merge_module(orc::ThreadSafeModule &destTSM, orc::ThreadSafeModule srcTSM) { - assert(dest != src.get()); - for (Module::global_iterator I = src->global_begin(), E = src->global_end(); I != E;) { + destTSM.withModuleDo([&](Module &dest) { + srcTSM.withModuleDo([&](Module &src) { + //TODO fix indentation after review + assert(&dest != &src && "Cannot merge module with itself!"); + assert(&dest.getContext() == &src.getContext() && "Cannot merge modules with different contexts!"); + assert(dest.getDataLayout() == src.getDataLayout() && "Cannot merge modules with different data layouts!"); + assert(dest.getTargetTriple() == src.getTargetTriple() && "Cannot merge modules with different target triples!"); + + for (Module::global_iterator I = src.global_begin(), E = src.global_end(); I != E;) { GlobalVariable *sG = &*I; - GlobalVariable *dG = cast_or_null(dest->getNamedValue(sG->getName())); + GlobalVariable *dG = cast_or_null(dest.getNamedValue(sG->getName())); ++I; // Replace a declaration with the definition: if (dG) { @@ -1251,14 +1269,14 @@ void jl_merge_module(Module *dest, std::unique_ptr src) } // Reparent the global variable: sG->removeFromParent(); - dest->getGlobalList().push_back(sG); + dest.getGlobalList().push_back(sG); // Comdat is owned by the Module sG->setComdat(nullptr); } - for (Module::iterator I = src->begin(), E = src->end(); I != E;) { + for (Module::iterator I = src.begin(), E = src.end(); I != E;) { Function *sG = &*I; - Function *dG = cast_or_null(dest->getNamedValue(sG->getName())); + Function *dG = cast_or_null(dest.getNamedValue(sG->getName())); ++I; // Replace a declaration with the definition: if (dG) { @@ -1275,14 +1293,14 @@ void jl_merge_module(Module *dest, std::unique_ptr src) } // Reparent the global variable: sG->removeFromParent(); - dest->getFunctionList().push_back(sG); + dest.getFunctionList().push_back(sG); // Comdat is owned by the Module sG->setComdat(nullptr); } - for (Module::alias_iterator I = src->alias_begin(), E = src->alias_end(); I != E;) { + for (Module::alias_iterator I = src.alias_begin(), E = src.alias_end(); I != E;) { GlobalAlias *sG = &*I; - GlobalAlias *dG = cast_or_null(dest->getNamedValue(sG->getName())); + GlobalAlias *dG = cast_or_null(dest.getNamedValue(sG->getName())); ++I; if (dG) { if (!dG->isDeclaration()) { // aliases are always definitions, so this test is reversed from the above two @@ -1296,18 +1314,20 @@ void jl_merge_module(Module *dest, std::unique_ptr src) } } sG->removeFromParent(); - dest->getAliasList().push_back(sG); + dest.getAliasList().push_back(sG); } // metadata nodes need to be explicitly merged not just copied // so there are special passes here for each known type of metadata - NamedMDNode *sNMD = src->getNamedMetadata("llvm.dbg.cu"); + NamedMDNode *sNMD = src.getNamedMetadata("llvm.dbg.cu"); if (sNMD) { - NamedMDNode *dNMD = dest->getOrInsertNamedMetadata("llvm.dbg.cu"); + NamedMDNode *dNMD = dest.getOrInsertNamedMetadata("llvm.dbg.cu"); for (NamedMDNode::op_iterator I = sNMD->op_begin(), E = sNMD->op_end(); I != E; ++I) { dNMD->addOperand(*I); } } + }); + }); } // optimize memory by turning long strings into memoized copies, instead of @@ -1353,10 +1373,10 @@ static void jl_decorate_module(Module &M) { } static int jl_add_to_ee( - std::unique_ptr &M, - StringMap*> &NewExports, - DenseMap &Queued, - std::vector*>> &ToMerge, + orc::ThreadSafeModule &M, + StringMap &NewExports, + DenseMap &Queued, + std::vector> &ToMerge, int depth) { // DAG-sort (post-dominator) the compile to compute the minimum @@ -1365,7 +1385,7 @@ static int jl_add_to_ee( return 0; // First check and record if it's on the stack somewhere { - auto &Cycle = Queued[M.get()]; + auto &Cycle = Queued[&M]; if (Cycle) return Cycle; ToMerge.push_back({}); @@ -1373,7 +1393,8 @@ static int jl_add_to_ee( } int MergeUp = depth; // Compute the cycle-id - for (auto &F : M->global_objects()) { + M.withModuleDo([&](Module &m) {//TODO fix indentation + for (auto &F : m.global_objects()) { if (F.isDeclaration() && F.getLinkage() == GlobalValue::ExternalLinkage) { auto Callee = NewExports.find(F.getName()); if (Callee != NewExports.end()) { @@ -1385,25 +1406,26 @@ static int jl_add_to_ee( } } } + }); if (MergeUp == depth) { // Not in a cycle (or at the top of it) - Queued.erase(M.get()); + Queued.erase(&M); for (auto &CM : ToMerge.at(depth - 1)) { - assert(Queued.find(CM->get())->second == depth); - Queued.erase(CM->get()); - jl_merge_module(M.get(), std::move(*CM)); + assert(Queued.find(CM)->second == depth); + Queued.erase(CM); + jl_merge_module(M, std::move(*CM)); } jl_ExecutionEngine->addModule(std::move(M)); MergeUp = 0; } else { // Add our frame(s) to the top of the cycle - Queued[M.get()] = MergeUp; + Queued[&M] = MergeUp; auto &Top = ToMerge.at(MergeUp - 1); Top.push_back(&M); for (auto &CM : ToMerge.at(depth - 1)) { - assert(Queued.find(CM->get())->second == depth); - Queued[CM->get()] = MergeUp; + assert(Queued.find(CM)->second == depth); + Queued[CM] = MergeUp; Top.push_back(CM); } } @@ -1411,10 +1433,10 @@ static int jl_add_to_ee( return MergeUp; } -static void jl_add_to_ee(std::unique_ptr &M, StringMap*> &NewExports) +static void jl_add_to_ee(orc::ThreadSafeModule &M, StringMap &NewExports) { - DenseMap Queued; - std::vector*>> ToMerge; + DenseMap Queued; + std::vector> ToMerge; jl_add_to_ee(M, NewExports, Queued, ToMerge, 1); assert(!M); } @@ -1438,8 +1460,3 @@ size_t jl_jit_total_bytes_impl(void) { return jl_ExecutionEngine->getTotalBytes(); } - -extern "C" JL_DLLEXPORT -LLVMContextRef jl_get_ee_context_impl(void) { - return wrap(jl_ExecutionEngine->getContext().getContext()); -} diff --git a/src/jitlayers.h b/src/jitlayers.h index c3024d8049577..79a3f40aed468 100644 --- a/src/jitlayers.h +++ b/src/jitlayers.h @@ -53,11 +53,10 @@ extern bool imaging_mode; void addTargetPasses(legacy::PassManagerBase *PM, TargetMachine *TM); void addOptimizationPasses(legacy::PassManagerBase *PM, int opt_level, bool lower_intrinsics=true, bool dump_native=false, bool external_use=false); void addMachinePasses(legacy::PassManagerBase *PM, TargetMachine *TM, int optlevel); -void jl_finalize_module(std::unique_ptr m); -void jl_merge_module(Module *dest, std::unique_ptr src); -Module *jl_create_llvm_module(StringRef name, LLVMContext &ctx, const DataLayout *DL = nullptr, const Triple *triple = nullptr); +void jl_finalize_module(orc::ThreadSafeModule m); +void jl_merge_module(orc::ThreadSafeModule &dest, orc::ThreadSafeModule src); GlobalVariable *jl_emit_RTLD_DEFAULT_var(Module *M); -DataLayout create_jl_data_layout(TargetMachine &TM); +DataLayout jl_create_datalayout(TargetMachine &TM); typedef struct _jl_llvm_functions_t { std::string functionObject; // jlcall llvm Function name @@ -79,10 +78,16 @@ struct jl_returninfo_t { unsigned return_roots; }; +struct jl_llvmf_dump_t { + orc::ThreadSafeModule TSM; + Function *F; +}; + typedef std::vector> jl_codegen_call_targets_t; -typedef std::tuple, jl_llvm_functions_t> jl_compile_result_t; typedef struct _jl_codegen_params_t { + orc::ThreadSafeContext tsctx; + orc::ThreadSafeContext::Lock tsctx_lock; typedef StringMap SymMapGV; // outputs jl_codegen_call_targets_t workqueue; @@ -108,30 +113,27 @@ typedef struct _jl_codegen_params_t { DenseMap, GlobalVariable*>> allPltMap; - Module *_shared_module = NULL; - Module *shared_module(LLVMContext &context) { - if (!_shared_module) - _shared_module = jl_create_llvm_module("globals", context); - return _shared_module; - } + orc::ThreadSafeModule _shared_module; + inline orc::ThreadSafeModule &shared_module(Module &from); // inputs size_t world = 0; const jl_cgparams_t *params = &jl_default_cgparams; bool cache = false; + _jl_codegen_params_t(orc::ThreadSafeContext ctx) : tsctx(std::move(ctx)), tsctx_lock(tsctx.getLock()) {} } jl_codegen_params_t; -jl_compile_result_t jl_emit_code( +jl_llvm_functions_t jl_emit_code( + orc::ThreadSafeModule &M, jl_method_instance_t *mi, jl_code_info_t *src, jl_value_t *jlrettype, - jl_codegen_params_t ¶ms, - LLVMContext &context); + jl_codegen_params_t ¶ms); -jl_compile_result_t jl_emit_codeinst( +jl_llvm_functions_t jl_emit_codeinst( + orc::ThreadSafeModule &M, jl_code_instance_t *codeinst, jl_code_info_t *src, - jl_codegen_params_t ¶ms, - LLVMContext &context); + jl_codegen_params_t ¶ms); enum CompilationPolicy { Default = 0, @@ -139,11 +141,13 @@ enum CompilationPolicy { ImagingMode = 2 }; +typedef std::map> jl_workqueue_t; + void jl_compile_workqueue( - std::map &emitted, + jl_workqueue_t &emitted, + Module &original, jl_codegen_params_t ¶ms, - CompilationPolicy policy, - LLVMContext &ctxt); + CompilationPolicy policy); Function *jl_cfunction_object(jl_function_t *f, jl_value_t *rt, jl_tupletype_t *argt, jl_codegen_params_t ¶ms); @@ -225,7 +229,7 @@ class JuliaOJIT { #endif void addGlobalMapping(StringRef Name, uint64_t Addr); - void addModule(std::unique_ptr M); + void addModule(orc::ThreadSafeModule M); JL_JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly); JL_JITSymbol findUnmangledSymbol(StringRef Name); @@ -272,6 +276,19 @@ class JuliaOJIT { DenseMap ReverseLocalSymbolTable; }; extern JuliaOJIT *jl_ExecutionEngine; +orc::ThreadSafeModule jl_create_llvm_module(StringRef name, orc::ThreadSafeContext ctx, const DataLayout &DL = jl_ExecutionEngine->getDataLayout(), const Triple &triple = jl_ExecutionEngine->getTargetTriple()); + +orc::ThreadSafeModule &jl_codegen_params_t::shared_module(Module &from) { + if (!_shared_module) { + _shared_module = jl_create_llvm_module("globals", tsctx, from.getDataLayout(), Triple(from.getTargetTriple())); + assert(&from.getContext() == tsctx.getContext() && "Module context differs from codegen_params context!"); + } else { + assert(&from.getContext() == _shared_module.getContext().getContext() && "Module context differs from shared module context!"); + assert(from.getDataLayout() == _shared_module.getModuleUnlocked()->getDataLayout() && "Module data layout differs from shared module data layout!"); + assert(from.getTargetTriple() == _shared_module.getModuleUnlocked()->getTargetTriple() && "Module target triple differs from shared module target triple!"); + } + return _shared_module; +} Pass *createLowerPTLSPass(bool imaging_mode); Pass *createCombineMulAddPass(); diff --git a/src/jl_exported_funcs.inc b/src/jl_exported_funcs.inc index af4588aa47163..54658db261c2f 100644 --- a/src/jl_exported_funcs.inc +++ b/src/jl_exported_funcs.inc @@ -523,8 +523,6 @@ YY(jl_dump_function_ir) \ YY(jl_dump_method_asm) \ YY(jl_extern_c) \ - YY(jl_get_ee_context) \ - YY(jl_get_llvm_context) \ YY(jl_get_llvmf_defn) \ YY(jl_get_llvm_function) \ YY(jl_get_llvm_module) \ diff --git a/src/julia_internal.h b/src/julia_internal.h index 1faf8e2c25245..5e1e8b02dc6c4 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -13,6 +13,7 @@ #include "support/rle.h" #include #include +#include #if !defined(_WIN32) #include #else @@ -665,7 +666,7 @@ JL_DLLEXPORT void jl_binding_deprecation_warning(jl_module_t *m, jl_binding_t *b extern jl_array_t *jl_module_init_order JL_GLOBALLY_ROOTED; extern htable_t jl_current_modules JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_module_t *jl_precompile_toplevel_module JL_GLOBALLY_ROOTED; -int jl_compile_extern_c(LLVMModuleRef llvmmod, void *params, void *sysimg, jl_value_t *declrt, jl_value_t *sigt); +int jl_compile_extern_c(LLVMOrcThreadSafeModuleRef llvmmod, void *params, void *sysimg, jl_value_t *declrt, jl_value_t *sigt); jl_opaque_closure_t *jl_new_opaque_closure(jl_tupletype_t *argt, jl_value_t *rt_lb, jl_value_t *rt_ub, jl_value_t *source, jl_value_t **env, size_t nenv); @@ -842,13 +843,12 @@ void jl_gc_set_permalloc_region(void *start, void *end); JL_DLLEXPORT jl_value_t *jl_dump_method_asm(jl_method_instance_t *linfo, size_t world, char raw_mc, char getwrapper, const char* asm_variant, const char *debuginfo, char binary); -JL_DLLEXPORT void *jl_get_llvmf_defn(jl_method_instance_t *linfo, LLVMContextRef ctxt, size_t world, char getwrapper, char optimize, const jl_cgparams_t params); +JL_DLLEXPORT void *jl_get_llvmf_defn(jl_method_instance_t *linfo, size_t world, char getwrapper, char optimize, const jl_cgparams_t params); JL_DLLEXPORT jl_value_t *jl_dump_fptr_asm(uint64_t fptr, char raw_mc, const char* asm_variant, const char *debuginfo, char binary); JL_DLLEXPORT jl_value_t *jl_dump_function_ir(void *f, char strip_ir_metadata, char dump_module, const char *debuginfo); JL_DLLEXPORT jl_value_t *jl_dump_function_asm(void *F, char raw_mc, const char* asm_variant, const char *debuginfo, char binary); -JL_DLLEXPORT LLVMContextRef jl_get_ee_context(void); -void *jl_create_native(jl_array_t *methods, LLVMContextRef llvmctxt, const jl_cgparams_t *cgparams, int policy); +void *jl_create_native(jl_array_t *methods, LLVMOrcThreadSafeModuleRef llvmmod, const jl_cgparams_t *cgparams, int policy); void jl_dump_native(void *native_code, const char *bc_fname, const char *unopt_bc_fname, const char *obj_fname, const char *asm_fname, const char *sysimg_data, size_t sysimg_len); diff --git a/src/runtime_intrinsics.c b/src/runtime_intrinsics.c index 9525b655dc5e3..89c9449e55920 100644 --- a/src/runtime_intrinsics.c +++ b/src/runtime_intrinsics.c @@ -8,9 +8,9 @@ // // TODO: add half-float support +#include "APInt-C.h" #include "julia.h" #include "julia_internal.h" -#include "APInt-C.h" const unsigned int host_char_bit = 8; diff --git a/stdlib/InteractiveUtils/src/codeview.jl b/stdlib/InteractiveUtils/src/codeview.jl index 2cd0bde0d8652..0df2f83c45ed8 100644 --- a/stdlib/InteractiveUtils/src/codeview.jl +++ b/stdlib/InteractiveUtils/src/codeview.jl @@ -188,8 +188,7 @@ function _dump_function_linfo_native(linfo::Core.MethodInstance, world::UInt, wr end function _dump_function_linfo_native(linfo::Core.MethodInstance, world::UInt, wrapper::Bool, syntax::Symbol, debuginfo::Symbol, binary::Bool, params::CodegenParams) - llvmctxt = ccall(:jl_get_ee_context, Ptr{Cvoid}, ()) - llvmf = ccall(:jl_get_llvmf_defn, Ptr{Cvoid}, (Any, Ptr{Cvoid}, UInt, Bool, Bool, CodegenParams), linfo, llvmctxt, world, wrapper, true, params) + llvmf = ccall(:jl_get_llvmf_defn, Ptr{Cvoid}, (Any, UInt, Bool, Bool, CodegenParams), linfo, world, wrapper, true, params) llvmf == C_NULL && error("could not compile the specified method") str = ccall(:jl_dump_function_asm, Ref{String}, (Ptr{Cvoid}, Bool, Ptr{UInt8}, Ptr{UInt8}, Bool), @@ -202,8 +201,7 @@ function _dump_function_linfo_llvm( strip_ir_metadata::Bool, dump_module::Bool, optimize::Bool, debuginfo::Symbol, params::CodegenParams) - llvmctxt = ccall(:jl_get_ee_context, Ptr{Cvoid}, ()) - llvmf = ccall(:jl_get_llvmf_defn, Ptr{Cvoid}, (Any, Ptr{Cvoid}, UInt, Bool, Bool, CodegenParams), linfo, llvmctxt, world, wrapper, optimize, params) + llvmf = ccall(:jl_get_llvmf_defn, Ptr{Cvoid}, (Any, UInt, Bool, Bool, CodegenParams), linfo, world, wrapper, optimize, params) llvmf == C_NULL && error("could not compile the specified method") str = ccall(:jl_dump_function_ir, Ref{String}, (Ptr{Cvoid}, Bool, Bool, Ptr{UInt8}),