diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp index 63358f0798411f..e90f2effd74d58 100644 --- a/src/aotcompile.cpp +++ b/src/aotcompile.cpp @@ -356,13 +356,13 @@ void *jl_create_native_impl(jl_array_t *methods, LLVMOrcThreadSafeModuleRef llvm JL_GC_POP(); // process the globals array, before jl_merge_module destroys them - std::vector gvars(params.globals.size()); - data->jl_value_to_llvm.resize(params.globals.size()); + std::vector gvars(params.global_targets.size()); + data->jl_value_to_llvm.resize(params.global_targets.size()); StringSet<> gvars_names; DenseSet gvars_set; size_t idx = 0; - for (auto &global : params.globals) { + for (auto &global : params.global_targets) { gvars[idx] = global.second->getName().str(); assert(gvars_set.insert(global.second).second && "Duplicate gvar in params!"); assert(gvars_names.insert(gvars[idx]).second && "Duplicate gvar name in params!"); @@ -2123,11 +2123,28 @@ void jl_get_llvmf_defn_impl(jl_llvmf_dump_t* dump, jl_method_instance_t *mi, siz Function *F = NULL; if (m) { // if compilation succeeded, prepare to return the result - // For imaging mode, global constants are currently private without initializer - // which isn't legal. Convert them to extern linkage so that the code can compile - // and will better match what's actually in sysimg. - for (auto &global : output.globals) - global.second->setLinkage(GlobalValue::ExternalLinkage); + // Similar to jl_link_global from jitlayers.cpp, + // so that code_llvm shows similar codegen to the jit + for (auto &global : output.global_targets) { + if (jl_options.image_codegen) { + global.second->setLinkage(GlobalValue::ExternalLinkage); + } else { + auto p = literal_static_pointer_val(global.first, global.second->getValueType()); + Type *elty; + if (p->getType()->isOpaquePointerTy()) { + elty = PointerType::get(output.getContext(), 0); + } else { + elty = p->getType()->getNonOpaquePointerElementType(); + } + // For pretty printing, when LLVM inlines the global initializer into its loads + auto alias = GlobalAlias::create(elty, 0, GlobalValue::PrivateLinkage, global.second->getName() + ".jit", p, m.getModuleUnlocked()); + global.second->setInitializer(ConstantExpr::getBitCast(alias, global.second->getValueType())); + global.second->setConstant(true); + global.second->setLinkage(GlobalValue::PrivateLinkage); + global.second->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); + global.second->setVisibility(GlobalValue::DefaultVisibility); + } + } assert(!verifyLLVMIR(*m.getModuleUnlocked())); if (optimize) { #ifndef JL_USE_NEW_PM diff --git a/src/ccall.cpp b/src/ccall.cpp index 47496a3a91ba60..0c0a1a2bc57cb9 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -2092,8 +2092,11 @@ jl_cgval_t function_sig_t::emit_a_ccall( } else if (symarg.fptr != NULL) { ++LiteralCCalls; - Type *funcptype = PointerType::get(functype, 0); - llvmf = literal_static_pointer_val((void*)(uintptr_t)symarg.fptr, funcptype); + Type *funcptype = functype->getPointerTo(0); + auto gv = julia_pgv(ctx, "ccall_fptr#", (void*)(uintptr_t)symarg.fptr); + auto casted = emit_bitcast(ctx, gv, funcptype->getPointerTo(0)); + llvmf = ctx.builder.CreateAlignedLoad(funcptype, casted, Align(sizeof(void*))); + setName(ctx.emission_context, llvmf, "ccall_fptr"); if (ctx.emission_context.imaging) jl_printf(JL_STDERR,"WARNING: literal address used in ccall for %s; code cannot be statically compiled\n", symarg.f_name); } diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 2551bd02c36c03..becf7076dd94d3 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -330,12 +330,12 @@ static Constant *julia_pgv(jl_codectx_t &ctx, const char *cname, void *addr) // emit a GlobalVariable for a jl_value_t named "cname" // store the name given so we can reuse it (facilitating merging later) // so first see if there already is a GlobalVariable for this address - GlobalVariable* &gv = ctx.global_targets[addr]; + GlobalVariable* &gv = ctx.emission_context.global_targets[addr]; Module *M = jl_Module; StringRef localname; std::string gvname; if (!gv) { - uint64_t id = ctx.emission_context.imaging ? jl_atomic_fetch_add(&globalUniqueGeneratedNames, 1) : ctx.global_targets.size(); + uint64_t id = ctx.emission_context.imaging ? jl_atomic_fetch_add(&globalUniqueGeneratedNames, 1) : ctx.emission_context.global_targets.size(); raw_string_ostream(gvname) << cname << id; localname = StringRef(gvname); } @@ -391,16 +391,6 @@ static Constant *literal_pointer_val_slot(jl_codectx_t &ctx, jl_value_t *p) { // emit a pointer to a jl_value_t* which will allow it to be valid across reloading code // also, try to give it a nice name for gdb, for easy identification - if (!ctx.emission_context.imaging) { - // TODO: this is an optimization, but is it useful or premature - // (it'll block any attempt to cache these, but can be simply deleted) - Module *M = jl_Module; - GlobalVariable *gv = new GlobalVariable( - *M, ctx.types().T_pjlvalue, true, GlobalVariable::PrivateLinkage, - literal_static_pointer_val(p, ctx.types().T_pjlvalue)); - gv->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); - return gv; - } if (JuliaVariable *gv = julia_const_gv(p)) { // if this is a known special object, use the existing GlobalValue return prepare_global_in(jl_Module, gv); @@ -513,8 +503,6 @@ static Value *literal_pointer_val(jl_codectx_t &ctx, jl_value_t *p) { if (p == NULL) return Constant::getNullValue(ctx.types().T_pjlvalue); - if (!ctx.emission_context.imaging) - return literal_static_pointer_val(p, ctx.types().T_pjlvalue); Value *pgv = literal_pointer_val_slot(ctx, p); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); auto load = ai.decorateInst(maybe_mark_load_dereferenceable( @@ -530,8 +518,6 @@ static Value *literal_pointer_val(jl_codectx_t &ctx, jl_binding_t *p) // emit a pointer to any jl_value_t which will be valid across reloading code if (p == NULL) return Constant::getNullValue(ctx.types().T_pjlvalue); - if (!ctx.emission_context.imaging) - return literal_static_pointer_val(p, ctx.types().T_pjlvalue); // bindings are prefixed with jl_bnd# jl_globalref_t *gr = p->globalref; Value *pgv = gr ? julia_pgv(ctx, "jl_bnd#", gr->name, gr->mod, p) : julia_pgv(ctx, "jl_bnd#", p); @@ -575,17 +561,12 @@ static Value *julia_binding_gv(jl_codectx_t &ctx, jl_binding_t *b) { // emit a literal_pointer_val to a jl_binding_t // binding->value are prefixed with * - if (ctx.emission_context.imaging) { - jl_globalref_t *gr = b->globalref; - Value *pgv = gr ? julia_pgv(ctx, "*", gr->name, gr->mod, b) : julia_pgv(ctx, "*jl_bnd#", b); - jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); - auto load = ai.decorateInst(ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, pgv, Align(sizeof(void*)))); - setName(ctx.emission_context, load, pgv->getName()); - return load; - } - else { - return literal_static_pointer_val(b, ctx.types().T_pjlvalue); - } + jl_globalref_t *gr = b->globalref; + Value *pgv = gr ? julia_pgv(ctx, "*", gr->name, gr->mod, b) : julia_pgv(ctx, "*jl_bnd#", b); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); + auto load = ai.decorateInst(ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, pgv, Align(sizeof(void*)))); + setName(ctx.emission_context, load, pgv->getName()); + return load; } // --- mapping between julia and llvm types --- @@ -1130,8 +1111,8 @@ static Value *emit_typeof(jl_codectx_t &ctx, const jl_cgval_t &p, bool maybenull p.typ, counter); auto emit_unboxty = [&] () -> Value* { - jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); if (ctx.emission_context.imaging) { + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); Value *datatype = ai.decorateInst(ctx.builder.CreateAlignedLoad(expr_type, datatype_or_p, Align(sizeof(void*)))); setName(ctx.emission_context, datatype, "typetag"); return justtag ? datatype : track_pjlvalue(ctx, datatype); diff --git a/src/codegen.cpp b/src/codegen.cpp index 9ec32746850f2e..e7a0824f9e996d 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1596,8 +1596,6 @@ class jl_codectx_t { IRBuilder<> builder; jl_codegen_params_t &emission_context; llvm::MapVector call_targets; - std::map &global_targets; - std::map, GlobalVariable*> &external_calls; Function *f = NULL; // local var info. globals are not in here. std::vector slots; @@ -1642,8 +1640,6 @@ class jl_codectx_t { : builder(llvmctx), emission_context(params), call_targets(), - global_targets(params.globals), - external_calls(params.external_fns), world(params.world), use_cache(params.cache), external_linkage(params.external_linkage), @@ -4298,7 +4294,7 @@ static jl_cgval_t emit_call_specfun_other(jl_codectx_t &ctx, bool is_opaque_clos GlobalVariable::ExternalLinkage, Constant::getNullValue(TheCallee->getType()), namep); - ctx.external_calls[std::make_tuple(fromexternal, true)] = GV; + ctx.emission_context.external_fns[std::make_tuple(fromexternal, true)] = GV; } jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); TheCallee = ai.decorateInst(ctx.builder.CreateAlignedLoad(TheCallee->getType(), GV, Align(sizeof(void*)))); @@ -4368,7 +4364,7 @@ static jl_cgval_t emit_call_specfun_boxed(jl_codectx_t &ctx, jl_value_t *jlretty GlobalVariable::ExternalLinkage, Constant::getNullValue(pfunc), namep); - ctx.external_calls[std::make_tuple(fromexternal, false)] = GV; + ctx.emission_context.external_fns[std::make_tuple(fromexternal, false)] = GV; } jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); theFptr = ai.decorateInst(ctx.builder.CreateAlignedLoad(pfunc, GV, Align(sizeof(void*)))); diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 986f2c713e03d8..59dc7047fc149b 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -214,7 +214,7 @@ static jl_callptr_t _jl_compile_codeinst( if (!params.imaging) { StringMap NewExports; StringMap NewGlobals; - for (auto &global : params.globals) { + for (auto &global : params.global_targets) { NewGlobals[global.second->getName()] = global.first; } for (auto &def : emitted) { @@ -243,7 +243,7 @@ static jl_callptr_t _jl_compile_codeinst( assert(Queued.empty() && Stack.empty() && !M); } } else { - jl_jit_globals(params.globals); + jl_jit_globals(params.global_targets); auto main = std::move(emitted[codeinst].first); for (auto &def : emitted) { if (def.first != codeinst) { @@ -372,7 +372,7 @@ int jl_compile_extern_c_impl(LLVMOrcThreadSafeModuleRef llvmmod, void *p, void * success = false; } if (success && p == NULL) { - jl_jit_globals(params.globals); + jl_jit_globals(params.global_targets); assert(params.workqueue.empty()); if (params._shared_module) jl_ExecutionEngine->addModule(orc::ThreadSafeModule(std::move(params._shared_module), params.tsctx)); diff --git a/src/jitlayers.h b/src/jitlayers.h index c2332eaeb9bd6c..e197b2a9eb9ec4 100644 --- a/src/jitlayers.h +++ b/src/jitlayers.h @@ -207,7 +207,7 @@ typedef struct _jl_codegen_params_t { typedef StringMap SymMapGV; // outputs std::vector> workqueue; - std::map globals; + std::map global_targets; std::map, GlobalVariable*> external_fns; std::map ditypes; std::map llvmtypes;