diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp index cf6378b4f926b..b1bef232e0915 100644 --- a/src/aotcompile.cpp +++ b/src/aotcompile.cpp @@ -305,6 +305,7 @@ void *jl_create_native_impl(jl_array_t *methods, LLVMOrcThreadSafeModuleRef llvm jl_codegen_params_t params(ctxt, std::move(target_info.first), std::move(target_info.second)); params.params = cgparams; params.imaging = imaging; + params.debug_level = jl_options.debug_level; params.external_linkage = _external_linkage; size_t compile_for[] = { jl_typeinf_world, _world }; for (int worlds = 0; worlds < 2; worlds++) { @@ -2082,6 +2083,16 @@ void jl_get_llvmf_defn_impl(jl_llvmf_dump_t* dump, jl_method_instance_t *mi, siz jl_codegen_params_t output(*ctx, std::move(target_info.first), std::move(target_info.second)); output.world = world; output.params = ¶ms; + output.imaging = imaging_default(); + // This would be nice, but currently it causes some assembly regressions that make printed output + // differ very significantly from the actual non-imaging mode code. + // // Force imaging mode for names of pointers + // output.imaging = true; + // This would also be nice, but it seems to cause OOMs on the windows32 builder + // // Force at least medium debug info for introspection + // No debug info = no variable names, + // max debug info = llvm.dbg.declare/value intrinsics which clutter IR output + output.debug_level = jl_options.debug_level; auto decls = jl_emit_code(m, mi, src, jlrettype, output); JL_UNLOCK(&jl_codegen_lock); // Might GC diff --git a/src/ccall.cpp b/src/ccall.cpp index 90f7417c03524..47496a3a91ba6 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -135,6 +135,7 @@ static Value *runtime_sym_lookup( BasicBlock *ccall_bb = BasicBlock::Create(irbuilder.getContext(), "ccall"); Constant *initnul = ConstantPointerNull::get(T_pvoidfunc); LoadInst *llvmf_orig = irbuilder.CreateAlignedLoad(T_pvoidfunc, llvmgv, Align(sizeof(void*))); + setName(emission_context, llvmf_orig, f_name + StringRef(".cached")); // This in principle needs a consume ordering so that load from // this pointer sees a valid value. However, this is not supported by // LLVM (or agreed on in the C/C++ standard FWIW) and should be @@ -143,8 +144,10 @@ static Value *runtime_sym_lookup( // invalid load from the `cglobal` but doesn't depend on the `cglobal` // value for this to happen. llvmf_orig->setAtomic(AtomicOrdering::Unordered); + auto nonnull = irbuilder.CreateICmpNE(llvmf_orig, initnul); + setName(emission_context, nonnull, "is_cached"); irbuilder.CreateCondBr( - irbuilder.CreateICmpNE(llvmf_orig, initnul), + nonnull, ccall_bb, dlsym_lookup); @@ -170,6 +173,7 @@ static Value *runtime_sym_lookup( llvmf = irbuilder.CreateCall(prepare_call_in(jl_builderModule(irbuilder), jldlsym_func), { libname, nameval, libptrgv }); } + setName(emission_context, llvmf, f_name + StringRef(".found")); StoreInst *store = irbuilder.CreateAlignedStore(llvmf, llvmgv, Align(sizeof(void*))); store->setAtomic(AtomicOrdering::Release); irbuilder.CreateBr(ccall_bb); @@ -179,6 +183,7 @@ static Value *runtime_sym_lookup( PHINode *p = irbuilder.CreatePHI(T_pvoidfunc, 2); p->addIncoming(llvmf_orig, enter_bb); p->addIncoming(llvmf, llvmf->getParent()); + setName(emission_context, p, f_name); return irbuilder.CreateBitCast(p, funcptype); } @@ -320,6 +325,7 @@ static Value *emit_plt( } GlobalVariable *got = prepare_global_in(jl_Module, sharedgot); LoadInst *got_val = ctx.builder.CreateAlignedLoad(got->getValueType(), got, Align(sizeof(void*))); + setName(ctx.emission_context, got_val, f_name); // See comment in `runtime_sym_lookup` above. This in principle needs a // consume ordering too. This is even less likely to cause issues though // since the only thing we do to this loaded pointer is to call it @@ -442,16 +448,20 @@ static Value *llvm_type_rewrite( unsigned align = std::max(DL.getPrefTypeAlignment(target_type), DL.getPrefTypeAlignment(from_type)); if (DL.getTypeAllocSize(target_type) >= DL.getTypeAllocSize(from_type)) { to = emit_static_alloca(ctx, target_type); + setName(ctx.emission_context, to, "type_rewrite_buffer"); cast(to)->setAlignment(Align(align)); from = emit_bitcast(ctx, to, from_type->getPointerTo()); } else { from = emit_static_alloca(ctx, from_type); + setName(ctx.emission_context, from, "type_rewrite_buffer"); cast(from)->setAlignment(Align(align)); to = emit_bitcast(ctx, from, target_type->getPointerTo()); } ctx.builder.CreateAlignedStore(v, from, Align(align)); - return ctx.builder.CreateAlignedLoad(target_type, to, Align(align)); + auto pun = ctx.builder.CreateAlignedLoad(target_type, to, Align(align)); + setName(ctx.emission_context, pun, "type_rewrite"); + return pun; } // --- argument passing and scratch space utilities --- @@ -508,6 +518,7 @@ static void typeassert_input(jl_codectx_t &ctx, const jl_cgval_t &jvinfo, jl_val Value *istype = ctx.builder.CreateICmpNE( ctx.builder.CreateCall(prepare_call(jlisa_func), { vx, boxed(ctx, jlto_runtime) }), ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0)); + setName(ctx.emission_context, istype, "istype"); BasicBlock *failBB = BasicBlock::Create(ctx.builder.getContext(), "fail", ctx.f); BasicBlock *passBB = BasicBlock::Create(ctx.builder.getContext(), "pass", ctx.f); ctx.builder.CreateCondBr(istype, passBB, failBB); @@ -545,6 +556,7 @@ static Value *julia_to_native( // pass the address of an alloca'd thing, not a box // since those are immutable. Value *slot = emit_static_alloca(ctx, to); + setName(ctx.emission_context, slot, "native_convert_buffer"); if (!jvinfo.ispointer()) { jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, jvinfo.tbaa); ai.decorateInst(ctx.builder.CreateStore(emit_unbox(ctx, to, jvinfo, jlto), slot)); @@ -1009,6 +1021,7 @@ static Value *box_ccall_result(jl_codectx_t &ctx, Value *result, Value *runtime_ unsigned nb = DL.getTypeStoreSize(result->getType()); MDNode *tbaa = jl_is_mutable(rt) ? ctx.tbaa().tbaa_mutab : ctx.tbaa().tbaa_immut; Value *strct = emit_allocobj(ctx, nb, runtime_dt); + setName(ctx.emission_context, strct, "ccall_result_box"); init_bits_value(ctx, strct, result, tbaa); return strct; } @@ -1253,6 +1266,7 @@ static bool verify_ref_type(jl_codectx_t &ctx, jl_value_t* ref, jl_unionall_t *u Value *notany = ctx.builder.CreateICmpNE( boxed(ctx, runtime_sp), track_pjlvalue(ctx, literal_pointer_val(ctx, (jl_value_t*)jl_any_type))); + setName(ctx.emission_context, notany, "any_type.not"); error_unless(ctx, notany, make_errmsg(fname, n, rt_err_msg_notany)); always_error = false; } @@ -1587,7 +1601,9 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) Value *ptask_i16 = emit_bitcast(ctx, get_current_task(ctx), getInt16PtrTy(ctx.builder.getContext())); const int tid_offset = offsetof(jl_task_t, tid); Value *ptid = ctx.builder.CreateInBoundsGEP(getInt16Ty(ctx.builder.getContext()), ptask_i16, ConstantInt::get(ctx.types().T_size, tid_offset / sizeof(int16_t))); + setName(ctx.emission_context, ptid, "thread_id_ptr"); LoadInst *tid = ctx.builder.CreateAlignedLoad(getInt16Ty(ctx.builder.getContext()), ptid, Align(sizeof(int16_t))); + setName(ctx.emission_context, tid, "thread_id"); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_gcframe); ai.decorateInst(tid); return mark_or_box_ccall_result(ctx, tid, retboxed, rt, unionall, static_rt); @@ -1601,15 +1617,19 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) Value *ptls_i32 = emit_bitcast(ctx, get_current_ptls(ctx), getInt32PtrTy(ctx.builder.getContext())); const int finh_offset = offsetof(jl_tls_states_t, finalizers_inhibited); Value *pfinh = ctx.builder.CreateInBoundsGEP(getInt32Ty(ctx.builder.getContext()), ptls_i32, ConstantInt::get(ctx.types().T_size, finh_offset / 4)); + setName(ctx.emission_context, pfinh, "finalizers_inhibited_ptr"); LoadInst *finh = ctx.builder.CreateAlignedLoad(getInt32Ty(ctx.builder.getContext()), pfinh, Align(sizeof(int32_t))); + setName(ctx.emission_context, finh, "finalizers_inhibited"); Value *newval; if (is_libjulia_func(jl_gc_disable_finalizers_internal)) { newval = ctx.builder.CreateAdd(finh, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 1)); + setName(ctx.emission_context, newval, "finalizers_inhibited_inc"); } else { newval = ctx.builder.CreateSelect(ctx.builder.CreateICmpEQ(finh, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0)), ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0), ctx.builder.CreateSub(finh, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 1))); + setName(ctx.emission_context, newval, "finalizers_inhibited_dec"); } ctx.builder.CreateStore(newval, pfinh); return ghostValue(ctx, jl_nothing_type); @@ -1630,6 +1650,7 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) Value *ptls_pv = emit_bitcast(ctx, get_current_ptls(ctx), ctx.types().T_ppjlvalue); const int nt_offset = offsetof(jl_tls_states_t, next_task); Value *pnt = ctx.builder.CreateInBoundsGEP(ctx.types().T_pjlvalue, ptls_pv, ConstantInt::get(ctx.types().T_size, nt_offset / sizeof(void*))); + setName(ctx.emission_context, pnt, "next_task_ptr"); ctx.builder.CreateStore(emit_pointer_from_objref(ctx, boxed(ctx, argv[0])), pnt); return ghostValue(ctx, jl_nothing_type); } @@ -1640,8 +1661,11 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) JL_GC_POP(); ctx.builder.CreateCall(prepare_call(gcroot_flush_func)); Value *pdefer_sig = emit_defer_signal(ctx); + setName(ctx.emission_context, pdefer_sig, "defer_signal_ptr"); Value *defer_sig = ctx.builder.CreateLoad(ctx.types().T_sigatomic, pdefer_sig); + setName(ctx.emission_context, defer_sig, "defer_signal"); defer_sig = ctx.builder.CreateAdd(defer_sig, ConstantInt::get(ctx.types().T_sigatomic, 1)); + setName(ctx.emission_context, defer_sig, "defer_signal_inc"); ctx.builder.CreateStore(defer_sig, pdefer_sig); emit_signal_fence(ctx); return ghostValue(ctx, jl_nothing_type); @@ -1653,7 +1677,9 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) JL_GC_POP(); ctx.builder.CreateCall(prepare_call(gcroot_flush_func)); Value *pdefer_sig = emit_defer_signal(ctx); + setName(ctx.emission_context, pdefer_sig, "defer_signal_ptr"); Value *defer_sig = ctx.builder.CreateLoad(ctx.types().T_sigatomic, pdefer_sig); + setName(ctx.emission_context, defer_sig, "defer_signal"); emit_signal_fence(ctx); error_unless(ctx, ctx.builder.CreateICmpNE(defer_sig, ConstantInt::get(ctx.types().T_sigatomic, 0)), @@ -1661,19 +1687,23 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) defer_sig = ctx.builder.CreateSub( defer_sig, ConstantInt::get(ctx.types().T_sigatomic, 1)); + setName(ctx.emission_context, defer_sig, "defer_signal_dec"); ctx.builder.CreateStore(defer_sig, pdefer_sig); BasicBlock *checkBB = BasicBlock::Create(ctx.builder.getContext(), "check", ctx.f); BasicBlock *contBB = BasicBlock::Create(ctx.builder.getContext(), "cont"); + auto not_deferred = ctx.builder.CreateICmpEQ(defer_sig, ConstantInt::get(ctx.types().T_sigatomic, 0)); + setName(ctx.emission_context, not_deferred, "deferred.not"); ctx.builder.CreateCondBr( - ctx.builder.CreateICmpEQ(defer_sig, ConstantInt::get(ctx.types().T_sigatomic, 0)), + not_deferred, checkBB, contBB); ctx.builder.SetInsertPoint(checkBB); - ctx.builder.CreateLoad( + auto signal_page_load = ctx.builder.CreateLoad( ctx.types().T_size, ctx.builder.CreateConstInBoundsGEP1_32(ctx.types().T_size, get_current_signal_page_from_ptls(ctx.builder, ctx.types().T_size, get_current_ptls(ctx), ctx.tbaa().tbaa_const), -1), true); + setName(ctx.emission_context, signal_page_load, "signal_page_load"); ctx.builder.CreateBr(contBB); ctx.f->getBasicBlockList().push_back(contBB); ctx.builder.SetInsertPoint(contBB); @@ -1690,7 +1720,9 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) } else { auto ptr = emit_bitcast(ctx, boxed(ctx, svecv), ctx.types().T_size->getPointerTo()); + setName(ctx.emission_context, ptr, "svec_len_ptr"); len = ctx.builder.CreateAlignedLoad(ctx.types().T_size, ptr, ctx.types().alignof_ptr); + setName(ctx.emission_context, len, "svec_len"); // Only mark with TBAA if we are sure about the type. // This could otherwise be in a dead branch if (svecv.typ == (jl_value_t*)jl_simplevector_type) { @@ -1713,11 +1745,15 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) const jl_cgval_t &idxv = argv[1]; Value *idx = emit_unbox(ctx, ctx.types().T_size, idxv, (jl_value_t*)jl_long_type); idx = ctx.builder.CreateAdd(idx, ConstantInt::get(ctx.types().T_size, 1)); + setName(ctx.emission_context, idx, "svec_idx"); auto ptr = emit_bitcast(ctx, boxed(ctx, svecv), ctx.types().T_pprjlvalue); + setName(ctx.emission_context, ptr, "svec_data_ptr"); Value *slot_addr = ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue, decay_derived(ctx, ptr), idx); + setName(ctx.emission_context, slot_addr, "svec_slot_addr"); LoadInst *load = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, slot_addr, Align(sizeof(void*))); + setName(ctx.emission_context, load, "svec_slot"); load->setAtomic(AtomicOrdering::Unordered); // Only mark with TBAA if we are sure about the type. // This could otherwise be in a dead branch @@ -1754,9 +1790,12 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) if (stride != 1) idx = ctx.builder.CreateMul(idx, ConstantInt::get(ctx.types().T_size, stride)); idx = ctx.builder.CreateAdd(idx, ConstantInt::get(ctx.types().T_size, ((jl_datatype_t*)ety)->layout->first_ptr)); + setName(ctx.emission_context, idx, "array_idx"); } Value *slot_addr = ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue, arrayptr, idx); + setName(ctx.emission_context, slot_addr, "array_slot_addr"); LoadInst *load = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, slot_addr, Align(sizeof(void*))); + setName(ctx.emission_context, load, "array_slot"); load->setAtomic(AtomicOrdering::Unordered); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_ptrarraybuf); ai.decorateInst(load); @@ -1776,6 +1815,7 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) // a null pointer. auto strp = ctx.builder.CreateConstInBoundsGEP1_32(ctx.types().T_prjlvalue, obj, 1); strp = ctx.builder.CreatePtrToInt(strp, ctx.types().T_size); + setName(ctx.emission_context, strp, "string_ptr"); JL_GC_POP(); return mark_or_box_ccall_result(ctx, strp, retboxed, rt, unionall, static_rt); } @@ -1790,6 +1830,7 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) auto strp = ctx.builder.CreateConstInBoundsGEP1_32( ctx.types().T_prjlvalue, obj, (sizeof(jl_sym_t) + sizeof(void*) - 1) / sizeof(void*)); strp = ctx.builder.CreatePtrToInt(strp, ctx.types().T_size); + setName(ctx.emission_context, strp, "symbol_name"); JL_GC_POP(); return mark_or_box_ccall_result(ctx, strp, retboxed, rt, unionall, static_rt); } @@ -1860,7 +1901,9 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) const int hash_offset = offsetof(jl_sym_t, hash); Value *ph1 = emit_bitcast(ctx, decay_derived(ctx, boxed(ctx, val)), ctx.types().T_size->getPointerTo()); Value *ph2 = ctx.builder.CreateInBoundsGEP(ctx.types().T_size, ph1, ConstantInt::get(ctx.types().T_size, hash_offset / ctx.types().sizeof_ptr)); + setName(ctx.emission_context, ph2, "object_id_ptr"); LoadInst *hashval = ctx.builder.CreateAlignedLoad(ctx.types().T_size, ph2, ctx.types().alignof_ptr); + setName(ctx.emission_context, hashval, "object_id"); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); ai.decorateInst(hashval); return mark_or_box_ccall_result(ctx, hashval, retboxed, rt, unionall, static_rt); @@ -1879,6 +1922,7 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) T_pint8_derived) }; Value *ret = ctx.builder.CreateCall(prepare_call(jl_object_id__func), makeArrayRef(args)); + setName(ctx.emission_context, ret, "object_id"); JL_GC_POP(); return mark_or_box_ccall_result(ctx, ret, retboxed, rt, unionall, static_rt); } @@ -1967,6 +2011,7 @@ jl_cgval_t function_sig_t::emit_a_ccall( assert(!retboxed && jl_is_datatype(rt) && "sret return type invalid"); if (jl_is_pointerfree(rt)) { result = emit_static_alloca(ctx, lrt); + setName(ctx.emission_context, result, "ccall_sret"); sretty = lrt; argvals[0] = ctx.builder.CreateBitCast(result, fargt_sig.at(0)); } @@ -1975,6 +2020,7 @@ jl_cgval_t function_sig_t::emit_a_ccall( // and has incorrect write barriers. // instead this code path should behave like `unsafe_load` result = emit_allocobj(ctx, (jl_datatype_t*)rt); + setName(ctx.emission_context, result, "ccall_sret_box"); sretty = ctx.types().T_jlvalue; sretboxed = true; gc_uses.push_back(result); @@ -2123,6 +2169,7 @@ jl_cgval_t function_sig_t::emit_a_ccall( return mark_julia_slot(result, rt, NULL, ctx.tbaa().tbaa_stack); ++SRetCCalls; result = ctx.builder.CreateLoad(sretty, result); + setName(ctx.emission_context, result, "returned"); } } else { @@ -2137,6 +2184,7 @@ jl_cgval_t function_sig_t::emit_a_ccall( assert(jl_is_datatype(rt)); if (static_rt) { Value *strct = emit_allocobj(ctx, (jl_datatype_t*)rt); + setName(ctx.emission_context, strct, "ccall_ret_box"); MDNode *tbaa = jl_is_mutable(rt) ? ctx.tbaa().tbaa_mutab : ctx.tbaa().tbaa_immut; int boxalign = julia_alignment(rt); // copy the data from the return value to the new struct @@ -2147,6 +2195,7 @@ jl_cgval_t function_sig_t::emit_a_ccall( // ARM and AArch64 can use a LLVM type larger than the julia type. // When this happens, cast through memory. auto slot = emit_static_alloca(ctx, resultTy); + setName(ctx.emission_context, slot, "type_pun_slot"); slot->setAlignment(Align(boxalign)); ctx.builder.CreateAlignedStore(result, slot, Align(boxalign)); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); diff --git a/src/cgutils.cpp b/src/cgutils.cpp index b400e510e0cde..8442ba99bb411 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -119,10 +119,12 @@ static Value *stringConstPtr( GlobalVariable *gv = get_pointer_to_constant(emission_context, Data, "_j_str", *M); Value *zero = ConstantInt::get(Type::getInt32Ty(irbuilder.getContext()), 0); Value *Args[] = { zero, zero }; - return irbuilder.CreateInBoundsGEP(gv->getValueType(), + auto gep = irbuilder.CreateInBoundsGEP(gv->getValueType(), // Addrspacecast in case globals are in non-0 AS irbuilder.CreateAddrSpaceCast(gv, gv->getValueType()->getPointerTo(0)), Args); + setName(emission_context, gep, "string_const_ptr"); + return gep; } @@ -515,9 +517,11 @@ static Value *literal_pointer_val(jl_codectx_t &ctx, jl_value_t *p) 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); - return ai.decorateInst(maybe_mark_load_dereferenceable( + auto load = ai.decorateInst(maybe_mark_load_dereferenceable( ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, pgv, Align(sizeof(void*))), false, jl_typeof(p))); + setName(ctx.emission_context, load, pgv->getName()); + return load; } // Returns ctx.types().T_pjlvalue @@ -532,9 +536,11 @@ static Value *literal_pointer_val(jl_codectx_t &ctx, jl_binding_t *p) 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); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); - return ai.decorateInst(maybe_mark_load_dereferenceable( + auto load = ai.decorateInst(maybe_mark_load_dereferenceable( ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, pgv, Align(sizeof(void*))), false, sizeof(jl_binding_t), alignof(jl_binding_t))); + setName(ctx.emission_context, load, pgv->getName()); + return load; } // bitcast a value, but preserve its address space when dealing with pointer types @@ -573,7 +579,9 @@ static Value *julia_binding_gv(jl_codectx_t &ctx, jl_binding_t *b) 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); - return ai.decorateInst(ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, pgv, Align(sizeof(void*)))); + 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); @@ -976,6 +984,10 @@ static void emit_memcpy_llvm(jl_codectx_t &ctx, Value *dst, jl_aliasinfo_t const src = emit_bitcast(ctx, src, dstty); } if (directel) { + if (isa(src) && !src->hasName()) + setName(ctx.emission_context, src, "memcpy_refined_src"); + if (isa(dst) && !dst->hasName()) + setName(ctx.emission_context, dst, "memcpy_refined_dst"); auto val = src_ai.decorateInst(ctx.builder.CreateAlignedLoad(directel, src, Align(align), is_volatile)); dst_ai.decorateInst(ctx.builder.CreateAlignedStore(val, dst, Align(align), is_volatile)); ++SkippedMemcpys; @@ -1035,6 +1047,7 @@ static LoadInst *emit_nthptr_recast(jl_codectx_t &ctx, Value *v, Value *idx, MDN ctx.types().T_prjlvalue, emit_bitcast(ctx, maybe_decay_tracked(ctx, v), ctx.types().T_pprjlvalue), idx); + setName(ctx.emission_context, vptr, "arraysize_ptr"); LoadInst *load = ctx.builder.CreateLoad(type, emit_bitcast(ctx, vptr, PointerType::get(type, 0))); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); ai.decorateInst(load); @@ -1045,7 +1058,9 @@ static Value *emit_tagfrom(jl_codectx_t &ctx, jl_datatype_t *dt) { if (dt->smalltag) return ConstantInt::get(ctx.types().T_size, dt->smalltag << 4); - return ctx.builder.CreatePtrToInt(literal_pointer_val(ctx, (jl_value_t*)dt), ctx.types().T_size); + auto tag = ctx.builder.CreatePtrToInt(literal_pointer_val(ctx, (jl_value_t*)dt), ctx.types().T_size); + setName(ctx.emission_context, tag, jl_symbol_name(dt->name->name)); + return tag; } // Returns justtag ? ctx.types.T_size : ctx.types().T_prjlvalue @@ -1110,6 +1125,7 @@ static Value *emit_typeof(jl_codectx_t &ctx, const jl_cgval_t &p, bool maybenull else ptr = ConstantExpr::getAddrSpaceCast(literal_static_pointer_val((jl_value_t*)jt, ctx.types().T_pjlvalue), expr_type); datatype_or_p = ctx.builder.CreateSelect(cmp, ptr, datatype_or_p); + setName(ctx.emission_context, datatype_or_p, "typetag_ptr"); }, p.typ, counter); @@ -1117,6 +1133,7 @@ static Value *emit_typeof(jl_codectx_t &ctx, const jl_cgval_t &p, bool maybenull jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); if (ctx.emission_context.imaging) { 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); } return datatype_or_p; @@ -1124,6 +1141,7 @@ static Value *emit_typeof(jl_codectx_t &ctx, const jl_cgval_t &p, bool maybenull Value *res; if (!allunboxed) { Value *isnull = ctx.builder.CreateIsNull(datatype_or_p); + setName(ctx.emission_context, isnull, "typetag_isnull"); BasicBlock *boxBB = BasicBlock::Create(ctx.builder.getContext(), "boxed", ctx.f); BasicBlock *unboxBB = BasicBlock::Create(ctx.builder.getContext(), "unboxed", ctx.f); BasicBlock *mergeBB = BasicBlock::Create(ctx.builder.getContext(), "merge", ctx.f); @@ -1141,6 +1159,7 @@ static Value *emit_typeof(jl_codectx_t &ctx, const jl_cgval_t &p, bool maybenull phi->addIncoming(boxTy, boxBB); phi->addIncoming(unboxTy, unboxBB); res = phi; + setName(ctx.emission_context, res, "typetag"); } else { res = emit_unboxty(); @@ -1155,15 +1174,19 @@ static Value *emit_datatype_types(jl_codectx_t &ctx, Value *dt) Value *Ptr = emit_bitcast(ctx, decay_derived(ctx, dt), ctx.types().T_ppjlvalue); Value *Idx = ConstantInt::get(ctx.types().T_size, offsetof(jl_datatype_t, types) / sizeof(void*)); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); - return ai.decorateInst(ctx.builder.CreateAlignedLoad( + auto types = ai.decorateInst(ctx.builder.CreateAlignedLoad( ctx.types().T_pjlvalue, ctx.builder.CreateInBoundsGEP(ctx.types().T_pjlvalue, Ptr, Idx), Align(sizeof(void*)))); + setName(ctx.emission_context, types, "datatype_types"); + return types; } static Value *emit_datatype_nfields(jl_codectx_t &ctx, Value *dt) { Value *type_svec = emit_bitcast(ctx, emit_datatype_types(ctx, dt), ctx.types().T_size->getPointerTo()); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); - return ai.decorateInst(ctx.builder.CreateAlignedLoad(ctx.types().T_size, type_svec, Align(sizeof(void*)))); + auto nfields = ai.decorateInst(ctx.builder.CreateAlignedLoad(ctx.types().T_size, type_svec, Align(sizeof(void*)))); + setName(ctx.emission_context, nfields, "datatype_nfields"); + return nfields; } static Value *emit_datatype_size(jl_codectx_t &ctx, Value *dt) @@ -1175,7 +1198,9 @@ static Value *emit_datatype_size(jl_codectx_t &ctx, Value *dt) Ptr = ai.decorateInst(ctx.builder.CreateAlignedLoad(getInt32PtrTy(ctx.builder.getContext()), Ptr, Align(sizeof(int32_t*)))); Idx = ConstantInt::get(ctx.types().T_size, offsetof(jl_datatype_layout_t, size) / sizeof(int32_t)); Ptr = ctx.builder.CreateInBoundsGEP(getInt32Ty(ctx.builder.getContext()), Ptr, Idx); - return ai.decorateInst(ctx.builder.CreateAlignedLoad(getInt32Ty(ctx.builder.getContext()), Ptr, Align(sizeof(int32_t)))); + auto Size = ai.decorateInst(ctx.builder.CreateAlignedLoad(getInt32Ty(ctx.builder.getContext()), Ptr, Align(sizeof(int32_t)))); + setName(ctx.emission_context, Size, "datatype_size"); + return Size; } /* this is valid code, it's simply unused @@ -1250,6 +1275,7 @@ static Value *emit_datatype_isprimitivetype(jl_codectx_t &ctx, Value *typ) isprimitive = ai.decorateInst(ctx.builder.CreateAlignedLoad(getInt8Ty(ctx.builder.getContext()), isprimitive, Align(1))); isprimitive = ctx.builder.CreateLShr(isprimitive, 7); isprimitive = ctx.builder.CreateTrunc(isprimitive, getInt1Ty(ctx.builder.getContext())); + setName(ctx.emission_context, isprimitive, "datatype_isprimitive"); return isprimitive; } @@ -1261,7 +1287,9 @@ static Value *emit_datatype_name(jl_codectx_t &ctx, Value *dt) emit_bitcast(ctx, maybe_decay_tracked(ctx, dt), ctx.types().T_ppjlvalue), ConstantInt::get(ctx.types().T_size, n)); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); - return ai.decorateInst(ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, vptr, Align(sizeof(void*)))); + auto name = ai.decorateInst(ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, vptr, Align(sizeof(void*)))); + setName(ctx.emission_context, name, "datatype_name"); + return name; } // --- generating various error checks --- @@ -1370,6 +1398,7 @@ static Value *emit_guarded_test(jl_codectx_t &ctx, Value *ifnot, Value *defval, PHINode *phi = ctx.builder.CreatePHI(defval->getType(), 2); phi->addIncoming(defval, currBB); phi->addIncoming(res, passBB); + setName(ctx.emission_context, phi, "guard_res"); return phi; } @@ -1414,7 +1443,7 @@ static Value *emit_typeof(jl_codectx_t &ctx, Value *v, bool maybenull, bool just assert(v != NULL && !isa(v) && "expected a conditionally boxed value"); Value *nonnull = maybenull ? null_pointer_cmp(ctx, v) : ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 1); Function *typeof = prepare_call(jl_typeof_func); - return emit_guarded_test(ctx, nonnull, Constant::getNullValue(justtag ? ctx.types().T_size : typeof->getReturnType()), [&] { + auto val = emit_guarded_test(ctx, nonnull, Constant::getNullValue(justtag ? ctx.types().T_size : typeof->getReturnType()), [&] { // e.g. emit_typeof(ctx, v) Value *typetag = ctx.builder.CreateCall(typeof, {v}); if (notag) @@ -1435,6 +1464,8 @@ static Value *emit_typeof(jl_codectx_t &ctx, Value *v, bool maybenull, bool just return ai.decorateInst(small); }); }); + setName(ctx.emission_context, val, "typeof"); + return val; } static Value *boxed(jl_codectx_t &ctx, const jl_cgval_t &v, bool is_promotable=false); @@ -1493,11 +1524,14 @@ static Value *emit_exactly_isa(jl_codectx_t &ctx, const jl_cgval_t &arg, jl_data if (tindex > 0) { // optimize more when we know that this is a split union-type where tindex = 0 is invalid Value *xtindex = ctx.builder.CreateAnd(arg.TIndex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x7f)); - return ctx.builder.CreateICmpEQ(xtindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), tindex)); + auto isa = ctx.builder.CreateICmpEQ(xtindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), tindex)); + setName(ctx.emission_context, isa, "exactly_isa"); + return isa; } else if (arg.Vboxed) { // test for (arg.TIndex == 0x80 && typeof(arg.V) == type) Value *isboxed = ctx.builder.CreateICmpEQ(arg.TIndex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80)); + setName(ctx.emission_context, isboxed, "isboxed"); BasicBlock *currBB = ctx.builder.GetInsertBlock(); BasicBlock *isaBB = BasicBlock::Create(ctx.builder.getContext(), "isa", ctx.f); BasicBlock *postBB = BasicBlock::Create(ctx.builder.getContext(), "post_isa", ctx.f); @@ -1510,13 +1544,16 @@ static Value *emit_exactly_isa(jl_codectx_t &ctx, const jl_cgval_t &arg, jl_data PHINode *istype = ctx.builder.CreatePHI(getInt1Ty(ctx.builder.getContext()), 2); istype->addIncoming(ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 0), currBB); istype->addIncoming(istype_boxed, isaBB); + setName(ctx.emission_context, istype, "exactly_isa"); return istype; } else { // handle the case where we know that `arg` is unboxed (but of unknown type), but that concrete type `type` cannot be unboxed return ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 0); } } - return ctx.builder.CreateICmpEQ(emit_typeof(ctx, arg, false, true), emit_tagfrom(ctx, dt)); + auto isa = ctx.builder.CreateICmpEQ(emit_typeof(ctx, arg, false, true), emit_tagfrom(ctx, dt)); + setName(ctx.emission_context, isa, "exactly_isa"); + return isa; } static std::pair emit_isa(jl_codectx_t &ctx, const jl_cgval_t &x, @@ -1586,6 +1623,7 @@ static std::pair emit_isa(jl_codectx_t &ctx, const jl_cgval_t &x, ctx.builder.CreateOr( ctx.builder.CreateICmpEQ(typ, emit_tagfrom(ctx, jl_unionall_type)), ctx.builder.CreateICmpEQ(typ, emit_tagfrom(ctx, jl_typeofbottom_type)))); + setName(ctx.emission_context, val, "is_kind"); return std::make_pair(val, false); } // intersection with Type needs to be handled specially @@ -1686,6 +1724,7 @@ static Value *emit_isconcrete(jl_codectx_t &ctx, Value *typ) isconcrete = ai.decorateInst(ctx.builder.CreateAlignedLoad(getInt8Ty(ctx.builder.getContext()), isconcrete, Align(1))); isconcrete = ctx.builder.CreateLShr(isconcrete, 1); isconcrete = ctx.builder.CreateTrunc(isconcrete, getInt1Ty(ctx.builder.getContext())); + setName(ctx.emission_context, isconcrete, "isconcrete"); return isconcrete; } @@ -1719,6 +1758,7 @@ static Value *emit_bounds_check(jl_codectx_t &ctx, const jl_cgval_t &ainfo, jl_v if (bounds_check_enabled(ctx, boundscheck)) { ++EmittedBoundschecks; Value *ok = ctx.builder.CreateICmpULT(im1, len); + setName(ctx.emission_context, ok, "boundscheck"); BasicBlock *failBB = BasicBlock::Create(ctx.builder.getContext(), "fail", ctx.f); BasicBlock *passBB = BasicBlock::Create(ctx.builder.getContext(), "pass"); ctx.builder.CreateCondBr(ok, passBB, failBB); @@ -1737,6 +1777,7 @@ static Value *emit_bounds_check(jl_codectx_t &ctx, const jl_cgval_t &ainfo, jl_v else if (!ainfo.ispointer()) { // CreateAlloca is OK here since we are on an error branch Value *tempSpace = ctx.builder.CreateAlloca(a->getType()); + setName(ctx.emission_context, tempSpace, "errorbox"); ctx.builder.CreateStore(a, tempSpace); a = tempSpace; } @@ -1828,12 +1869,15 @@ static jl_cgval_t typed_load(jl_codectx_t &ctx, Value *ptr, Value *idx_0based, j // note that nb == jl_Module->getDataLayout().getTypeAllocSize(elty) or getTypeStoreSize, depending on whether it is a struct or primitive type AllocaInst *intcast = NULL; if (Order == AtomicOrdering::NotAtomic) { - if (!isboxed && !aliasscope && elty->isAggregateType() && !CountTrackedPointers(elty).count) + if (!isboxed && !aliasscope && elty->isAggregateType() && !CountTrackedPointers(elty).count) { intcast = emit_static_alloca(ctx, elty); + setName(ctx.emission_context, intcast, "aggregate_load_box"); + } } else { if (!isboxed && !elty->isIntOrPtrTy()) { intcast = emit_static_alloca(ctx, elty); + setName(ctx.emission_context, intcast, "atomic_load_box"); elty = Type::getIntNTy(ctx.builder.getContext(), 8 * nb); } } @@ -1949,8 +1993,10 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx, unsigned nb = isboxed ? sizeof(void*) : jl_datatype_size(jltype); AllocaInst *intcast = nullptr; if (!isboxed && Order != AtomicOrdering::NotAtomic && !elty->isIntOrPtrTy()) { - if (!issetfield) + if (!issetfield) { intcast = emit_static_alloca(ctx, elty); + setName(ctx.emission_context, intcast, "atomic_store_box"); + } elty = Type::getIntNTy(ctx.builder.getContext(), 8 * nb); } Type *realelty = elty; @@ -1988,6 +2034,7 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx, if (issetfield || (Order == AtomicOrdering::NotAtomic && isswapfield)) { if (isswapfield) { auto *load = ctx.builder.CreateAlignedLoad(elty, ptr, Align(alignment)); + setName(ctx.emission_context, load, "swapfield_load"); if (isboxed) load->setOrdering(AtomicOrdering::Unordered); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); @@ -2011,6 +2058,7 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx, else if (isswapfield && isStrongerThanMonotonic(Order)) { assert(Order != AtomicOrdering::NotAtomic && r); auto *store = ctx.builder.CreateAtomicRMW(AtomicRMWInst::Xchg, ptr, r, Align(alignment), Order); + setName(ctx.emission_context, store, "swapfield_atomicrmw"); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); ai.noalias = MDNode::concatenate(aliasscope, ai.noalias); ai.decorateInst(store); @@ -2035,6 +2083,7 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx, ctx.builder.CreateCondBr(SameType, BB, SkipBB); ctx.builder.SetInsertPoint(SkipBB); LoadInst *load = ctx.builder.CreateAlignedLoad(elty, ptr, Align(alignment)); + setName(ctx.emission_context, load, "atomic_replacefield_initial"); load->setOrdering(FailOrder == AtomicOrdering::NotAtomic && isboxed ? AtomicOrdering::Monotonic : FailOrder); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); ai.noalias = MDNode::concatenate(aliasscope, ai.noalias); @@ -2065,6 +2114,7 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx, else { // swap or modify LoadInst *Current = ctx.builder.CreateAlignedLoad(elty, ptr, Align(alignment)); Current->setOrdering(Order == AtomicOrdering::NotAtomic && !isboxed ? Order : AtomicOrdering::Monotonic); + setName(ctx.emission_context, Current, "atomic_initial"); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); ai.noalias = MDNode::concatenate(aliasscope, ai.noalias); Compare = ai.decorateInst(Current); @@ -2267,8 +2317,10 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx, // Returns ctx.types().T_pjlvalue static Value *julia_bool(jl_codectx_t &ctx, Value *cond) { - return ctx.builder.CreateSelect(cond, literal_pointer_val(ctx, jl_true), + auto boolean = ctx.builder.CreateSelect(cond, literal_pointer_val(ctx, jl_true), literal_pointer_val(ctx, jl_false)); + setName(ctx.emission_context, boolean, "bool"); + return boolean; } // --- accessing the representations of built-in data types --- @@ -2354,6 +2406,7 @@ static bool emit_getfield_unknownidx(jl_codectx_t &ctx, ctx.builder.CreateExtractValue(strct.V, makeArrayRef(i)), fld); } + setName(ctx.emission_context, fld, "getfield"); jl_value_t *jft = issame ? jl_svecref(types, 0) : (jl_value_t*)jl_any_type; if (isboxed && maybe_null) null_pointer_check(ctx, fld); @@ -2387,7 +2440,9 @@ static bool emit_getfield_unknownidx(jl_codectx_t &ctx, ctx.types().T_prjlvalue, emit_bitcast(ctx, data_pointer(ctx, strct), ctx.types().T_pprjlvalue), idx0()); + setName(ctx.emission_context, fldptr, "getfield_ptr"); LoadInst *fld = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, fldptr, Align(sizeof(void*))); + setName(ctx.emission_context, fld, "getfield"); fld->setOrdering(AtomicOrdering::Unordered); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, strct.tbaa); ai.decorateInst(fld); @@ -2439,6 +2494,7 @@ static jl_cgval_t emit_unionload(jl_codectx_t &ctx, Value *addr, Value *ptindex, // move value to an immutable stack slot (excluding tindex) Type *AT = ArrayType::get(IntegerType::get(ctx.builder.getContext(), 8 * al), (fsz + al - 1) / al); AllocaInst *lv = emit_static_alloca(ctx, AT); + setName(ctx.emission_context, lv, "immutable_union"); if (al > 1) lv->setAlignment(Align(al)); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); @@ -2509,7 +2565,9 @@ static jl_cgval_t emit_getfield_knownidx(jl_codectx_t &ctx, const jl_cgval_t &st addr = ctx.builder.CreateConstInBoundsGEP2_32(lt, staddr, 0, idx); } if (jl_field_isptr(jt, idx)) { + setName(ctx.emission_context, addr, "getfield_addr"); LoadInst *Load = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, maybe_bitcast(ctx, addr, ctx.types().T_pprjlvalue), Align(sizeof(void*))); + setName(ctx.emission_context, Load, "getfield"); Load->setOrdering(order <= jl_memory_order_notatomic ? AtomicOrdering::Unordered : get_llvm_atomic_order(order)); maybe_mark_load_dereferenceable(Load, maybe_null, jl_field_type(jt, idx)); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); @@ -2572,6 +2630,7 @@ static jl_cgval_t emit_getfield_knownidx(jl_codectx_t &ctx, const jl_cgval_t &st IntegerType *ET = cast(T->getStructElementType(st_idx)); unsigned align = (ET->getBitWidth() + 7) / 8; lv = emit_static_alloca(ctx, ET); + setName(ctx.emission_context, lv, "union_split"); lv->setOperand(0, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), (fsz + align - 1) / align)); // emit all of the align-sized words unsigned i = 0; @@ -2715,6 +2774,7 @@ static Value *emit_arraysize(jl_codectx_t &ctx, const jl_cgval_t &tinfo, Value * t, ctx.builder.CreateAdd(dim, ConstantInt::get(dim->getType(), o)), tbaa, ctx.types().T_size); + setName(ctx.emission_context, load, "arraysize"); MDBuilder MDB(ctx.builder.getContext()); auto rng = MDB.createRange(Constant::getNullValue(ctx.types().T_size), ConstantInt::get(ctx.types().T_size, arraytype_maxsize(tinfo.typ))); load->setMetadata(LLVMContext::MD_range, rng); @@ -2750,7 +2810,9 @@ static Value *emit_arraylen_prim(jl_codectx_t &ctx, const jl_cgval_t &tinfo) Value *addr = ctx.builder.CreateStructGEP(ctx.types().T_jlarray, emit_bitcast(ctx, decay_derived(ctx, t), ctx.types().T_pjlarray), 1); //index (not offset) of length field in ctx.types().T_pjlarray + setName(ctx.emission_context, addr, "arraylen_ptr"); LoadInst *len = ctx.builder.CreateAlignedLoad(ctx.types().T_size, addr, ctx.types().alignof_ptr); + setName(ctx.emission_context, len, "arraylen"); len->setOrdering(AtomicOrdering::NotAtomic); MDBuilder MDB(ctx.builder.getContext()); auto rng = MDB.createRange(Constant::getNullValue(ctx.types().T_size), ConstantInt::get(ctx.types().T_size, arraytype_maxsize(tinfo.typ))); @@ -2769,6 +2831,7 @@ static Value *emit_arrayptr_internal(jl_codectx_t &ctx, const jl_cgval_t &tinfo, ++EmittedArrayptr; Value *addr = ctx.builder.CreateStructGEP(ctx.types().T_jlarray, emit_bitcast(ctx, t, ctx.types().T_pjlarray), 0); + setName(ctx.emission_context, addr, "arrayptr_ptr"); // Normally allocated array of 0 dimension always have a inline pointer. // However, we can't rely on that here since arrays can also be constructed from C pointers. PointerType *PT = cast(addr->getType()); @@ -2787,6 +2850,7 @@ static Value *emit_arrayptr_internal(jl_codectx_t &ctx, const jl_cgval_t &tinfo, } LoadInst *LI = ctx.builder.CreateAlignedLoad(LoadT, addr, Align(sizeof(char *))); + setName(ctx.emission_context, LI, "arrayptr"); LI->setOrdering(AtomicOrdering::NotAtomic); LI->setMetadata(LLVMContext::MD_nonnull, MDNode::get(ctx.builder.getContext(), None)); jl_aliasinfo_t aliasinfo = jl_aliasinfo_t::fromTBAA(ctx, arraytype_constshape(tinfo.typ) ? ctx.tbaa().tbaa_const : ctx.tbaa().tbaa_arrayptr); @@ -2827,8 +2891,11 @@ static Value *emit_arrayflags(jl_codectx_t &ctx, const jl_cgval_t &tinfo) ctx.types().T_jlarray, emit_bitcast(ctx, decay_derived(ctx, t), ctx.types().T_pjlarray), arrayflag_field); + setName(ctx.emission_context, addr, "arrayflags_ptr"); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_arrayflags); - return ai.decorateInst(ctx.builder.CreateAlignedLoad(getInt16Ty(ctx.builder.getContext()), addr, Align(sizeof(int16_t)))); + auto flags = ai.decorateInst(ctx.builder.CreateAlignedLoad(getInt16Ty(ctx.builder.getContext()), addr, Align(sizeof(int16_t)))); + setName(ctx.emission_context, flags, "arrayflags"); + return flags; } static Value *emit_arrayndims(jl_codectx_t &ctx, const jl_cgval_t &ary) @@ -2838,6 +2905,7 @@ static Value *emit_arrayndims(jl_codectx_t &ctx, const jl_cgval_t &ary) cast(flags)->setMetadata(LLVMContext::MD_invariant_load, MDNode::get(ctx.builder.getContext(), None)); flags = ctx.builder.CreateLShr(flags, 2); flags = ctx.builder.CreateAnd(flags, 0x1FF); // (1<<9) - 1 + setName(ctx.emission_context, flags, "arrayndims"); return flags; } @@ -2849,8 +2917,11 @@ static Value *emit_arrayelsize(jl_codectx_t &ctx, const jl_cgval_t &tinfo) Value *addr = ctx.builder.CreateStructGEP(ctx.types().T_jlarray, emit_bitcast(ctx, decay_derived(ctx, t), ctx.types().T_pjlarray), elsize_field); + setName(ctx.emission_context, addr, "arrayelsize_ptr"); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); - return ai.decorateInst(ctx.builder.CreateAlignedLoad(getInt16Ty(ctx.builder.getContext()), addr, Align(sizeof(int16_t)))); + auto elsize = ai.decorateInst(ctx.builder.CreateAlignedLoad(getInt16Ty(ctx.builder.getContext()), addr, Align(sizeof(int16_t)))); + setName(ctx.emission_context, elsize, "arrayelsize"); + return elsize; } static Value *emit_arrayoffset(jl_codectx_t &ctx, const jl_cgval_t &tinfo, int nd) @@ -2865,8 +2936,11 @@ static Value *emit_arrayoffset(jl_codectx_t &ctx, const jl_cgval_t &tinfo, int n ctx.types().T_jlarray, emit_bitcast(ctx, decay_derived(ctx, t), ctx.types().T_pjlarray), offset_field); + setName(ctx.emission_context, addr, "arrayoffset_ptr"); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_arrayoffset); - return ai.decorateInst(ctx.builder.CreateAlignedLoad(getInt32Ty(ctx.builder.getContext()), addr, Align(sizeof(int32_t)))); + auto offset = ai.decorateInst(ctx.builder.CreateAlignedLoad(getInt32Ty(ctx.builder.getContext()), addr, Align(sizeof(int32_t)))); + setName(ctx.emission_context, offset, "arrayoffset"); + return offset; } // Returns the size of the array represented by `tinfo` for the given dimension `dim` if @@ -2909,12 +2983,15 @@ static Value *emit_array_nd_index( if (bc) { BasicBlock *okBB = BasicBlock::Create(ctx.builder.getContext(), "ib"); // if !(i < d) goto error - ctx.builder.CreateCondBr(ctx.builder.CreateICmpULT(ii, d), okBB, failBB); + auto bc = ctx.builder.CreateICmpULT(ii, d); + setName(ctx.emission_context, bc, "inbounds"); + ctx.builder.CreateCondBr(bc, okBB, failBB); ctx.f->getBasicBlockList().push_back(okBB); ctx.builder.SetInsertPoint(okBB); } #endif stride = ctx.builder.CreateMul(stride, d); + setName(ctx.emission_context, stride, "stride"); } } #if CHECK_BOUNDS==1 @@ -2924,20 +3001,26 @@ static Value *emit_array_nd_index( if (nidxs == 1) { // Linear indexing: Check against the entire linear span of the array Value *alen = emit_arraylen(ctx, ainfo); - ctx.builder.CreateCondBr(ctx.builder.CreateICmpULT(i, alen), endBB, failBB); + auto bc = ctx.builder.CreateICmpULT(i, alen); + setName(ctx.emission_context, bc, "inbounds"); + ctx.builder.CreateCondBr(bc, endBB, failBB); } else if (nidxs >= (size_t)nd){ // No dimensions were omitted; just check the last remaining index assert(nd >= 0); Value *last_index = ii; Value *last_dimension = emit_arraysize_for_unsafe_dim(ctx, ainfo, ex, nidxs, nd); - ctx.builder.CreateCondBr(ctx.builder.CreateICmpULT(last_index, last_dimension), endBB, failBB); + auto bc = ctx.builder.CreateICmpULT(last_index, last_dimension); + setName(ctx.emission_context, bc, "inbounds"); + ctx.builder.CreateCondBr(bc, endBB, failBB); } else { // There were fewer indices than dimensions; check the last remaining index BasicBlock *checktrailingdimsBB = BasicBlock::Create(ctx.builder.getContext(), "dimsib"); assert(nd >= 0); Value *last_index = ii; Value *last_dimension = emit_arraysize_for_unsafe_dim(ctx, ainfo, ex, nidxs, nd); - ctx.builder.CreateCondBr(ctx.builder.CreateICmpULT(last_index, last_dimension), checktrailingdimsBB, failBB); + auto bc = ctx.builder.CreateICmpULT(last_index, last_dimension); + setName(ctx.emission_context, bc, "inbounds"); + ctx.builder.CreateCondBr(bc, checktrailingdimsBB, failBB); ctx.f->getBasicBlockList().push_back(checktrailingdimsBB); ctx.builder.SetInsertPoint(checktrailingdimsBB); // And then also make sure that all dimensions that weren't explicitly @@ -2945,18 +3028,23 @@ static Value *emit_array_nd_index( for (size_t k = nidxs+1; k < (size_t)nd; k++) { BasicBlock *dimsokBB = BasicBlock::Create(ctx.builder.getContext(), "dimsok"); Value *dim = emit_arraysize_for_unsafe_dim(ctx, ainfo, ex, k, nd); - ctx.builder.CreateCondBr(ctx.builder.CreateICmpEQ(dim, ConstantInt::get(ctx.types().T_size, 1)), dimsokBB, failBB); + auto bc = ctx.builder.CreateICmpEQ(dim, ConstantInt::get(ctx.types().T_size, 1)); + setName(ctx.emission_context, bc, "inbounds"); + ctx.builder.CreateCondBr(bc, dimsokBB, failBB); ctx.f->getBasicBlockList().push_back(dimsokBB); ctx.builder.SetInsertPoint(dimsokBB); } Value *dim = emit_arraysize_for_unsafe_dim(ctx, ainfo, ex, nd, nd); - ctx.builder.CreateCondBr(ctx.builder.CreateICmpEQ(dim, ConstantInt::get(ctx.types().T_size, 1)), endBB, failBB); + auto bc2 = ctx.builder.CreateICmpEQ(dim, ConstantInt::get(ctx.types().T_size, 1)); + setName(ctx.emission_context, bc2, "inbounds"); + ctx.builder.CreateCondBr(bc2, endBB, failBB); } ctx.f->getBasicBlockList().push_back(failBB); ctx.builder.SetInsertPoint(failBB); // CreateAlloca is OK here since we are on an error branch Value *tmp = ctx.builder.CreateAlloca(ctx.types().T_size, ConstantInt::get(ctx.types().T_size, nidxs)); + setName(ctx.emission_context, tmp, "errorbox"); for (size_t k = 0; k < nidxs; k++) { ctx.builder.CreateAlignedStore(idxs[k], ctx.builder.CreateInBoundsGEP(ctx.types().T_size, tmp, ConstantInt::get(ctx.types().T_size, k)), ctx.types().alignof_ptr); } @@ -3174,6 +3262,7 @@ static Value *compute_box_tindex(jl_codectx_t &ctx, Value *datatype_tag, jl_valu }, ut, counter); + setName(ctx.emission_context, tindex, "tindex"); return tindex; } @@ -3224,6 +3313,7 @@ static AllocaInst *try_emit_union_alloca(jl_codectx_t &ctx, jl_uniontype_t *ut, // try to pick an Integer type size such that SROA will emit reasonable code Type *AT = ArrayType::get(IntegerType::get(ctx.builder.getContext(), 8 * min_align), (nbytes + min_align - 1) / min_align); AllocaInst *lv = emit_static_alloca(ctx, AT); + setName(ctx.emission_context, lv, "unionalloca"); if (align > 1) lv->setAlignment(Align(align)); return lv; @@ -3280,6 +3370,7 @@ static Value *box_union(jl_codectx_t &ctx, const jl_cgval_t &vinfo, const SmallB box = _boxed_special(ctx, vinfo_r, t); if (!box) { box = emit_allocobj(ctx, jt); + setName(ctx.emission_context, box, "unionbox"); init_bits_cgval(ctx, box, vinfo_r, jl_is_mutable(jt) ? ctx.tbaa().tbaa_mutab : ctx.tbaa().tbaa_immut); } } @@ -3408,6 +3499,7 @@ static Value *boxed(jl_codectx_t &ctx, const jl_cgval_t &vinfo, bool is_promotab box = emit_allocobj(ctx, (jl_datatype_t*)jt); Value *decayed = decay_derived(ctx, box); AllocaInst *originalAlloca = cast(vinfo.V); + box->takeName(originalAlloca); decayed = maybe_bitcast(ctx, decayed, PointerType::getWithSamePointeeType(originalAlloca->getType(), AddressSpace::Derived)); // Warning: Very illegal IR here temporarily originalAlloca->mutateType(decayed->getType()); @@ -3418,6 +3510,7 @@ static Value *boxed(jl_codectx_t &ctx, const jl_cgval_t &vinfo, bool is_promotab ctx.builder.restoreIP(IP); } else { box = emit_allocobj(ctx, (jl_datatype_t*)jt); + setName(ctx.emission_context, box, "box"); init_bits_cgval(ctx, box, vinfo, jl_is_mutable(jt) ? ctx.tbaa().tbaa_mutab : ctx.tbaa().tbaa_immut); } } @@ -3528,6 +3621,7 @@ static void emit_cpointercheck(jl_codectx_t &ctx, const jl_cgval_t &x, const std Value *istype = ctx.builder.CreateICmpEQ(emit_datatype_name(ctx, t), literal_pointer_val(ctx, (jl_value_t*)jl_pointer_typename)); + setName(ctx.emission_context, istype, "istype"); BasicBlock *failBB = BasicBlock::Create(ctx.builder.getContext(), "fail", ctx.f); BasicBlock *passBB = BasicBlock::Create(ctx.builder.getContext(), "pass"); ctx.builder.CreateCondBr(istype, passBB, failBB); @@ -3769,6 +3863,7 @@ static jl_cgval_t emit_new_struct(jl_codectx_t &ctx, jl_value_t *ty, size_t narg } else { strct = emit_static_alloca(ctx, lt); + setName(ctx.emission_context, strct, "newstruct"); if (tracked.count) undef_derived_strct(ctx, strct, sty, ctx.tbaa().tbaa_stack); } @@ -3847,6 +3942,7 @@ static jl_cgval_t emit_new_struct(jl_codectx_t &ctx, jl_value_t *ty, size_t narg Type *ET = IntegerType::get(ctx.builder.getContext(), 8 * al); assert(lt->getStructElementType(llvm_idx) == ET); AllocaInst *lv = emit_static_alloca(ctx, ET); + setName(ctx.emission_context, lv, "unioninit"); lv->setOperand(0, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), (fsz + al - 1) / al)); emit_unionmove(ctx, lv, ctx.tbaa().tbaa_stack, fval_info, nullptr); // emit all of the align-sized words @@ -3937,6 +4033,7 @@ static jl_cgval_t emit_new_struct(jl_codectx_t &ctx, jl_value_t *ty, size_t narg } } Value *strct = emit_allocobj(ctx, sty); + setName(ctx.emission_context, strct, "newstruct"); jl_cgval_t strctinfo = mark_julia_type(ctx, strct, true, ty); strct = decay_derived(ctx, strct); undef_derived_strct(ctx, strct, sty, strctinfo.tbaa); diff --git a/src/codegen.cpp b/src/codegen.cpp index 37281ed3038ec..137d3d78814af 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -167,6 +167,13 @@ typedef Instruction TerminatorInst; #undef DEBUG_TYPE //LLVM occasionally likes to set DEBUG_TYPE in a header... #define DEBUG_TYPE "julia_irgen_codegen" +void setName(jl_codegen_params_t ¶ms, Value *V, const Twine &Name) +{ + if (params.debug_level) { + V->setName(Name); + } +} + STATISTIC(EmittedAllocas, "Number of allocas emitted"); STATISTIC(EmittedIntToPtrs, "Number of inttoptrs emitted"); STATISTIC(ModulesCreated, "Number of LLVM Modules created"); @@ -1604,7 +1611,6 @@ class jl_codectx_t { Value *pgcstack = NULL; Instruction *topalloca = NULL; - bool debug_enabled = false; bool use_cache = false; bool external_linkage = false; const jl_cgparams_t *params = NULL; @@ -2024,6 +2030,7 @@ static void alloc_def_flag(jl_codectx_t &ctx, jl_varinfo_t& vi) assert((!vi.boxroot || vi.pTIndex) && "undef check is null pointer for boxed things"); if (vi.usedUndef) { vi.defFlag = emit_static_alloca(ctx, getInt1Ty(ctx.builder.getContext())); + setName(ctx.emission_context, vi.defFlag, "isdefined"); store_def_flag(ctx, vi, false); } } @@ -2122,6 +2129,7 @@ static jl_cgval_t convert_julia_type_union(jl_codectx_t &ctx, const jl_cgval_t & v.typ, counter); } + setName(ctx.emission_context, new_tindex, "tindex"); // some of the values are still unboxed if (!isa(new_tindex)) { @@ -2136,6 +2144,7 @@ static jl_cgval_t convert_julia_type_union(jl_codectx_t &ctx, const jl_cgval_t & wasboxed = ctx.builder.CreateAnd(v.TIndex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80)); new_tindex = ctx.builder.CreateOr(wasboxed, new_tindex); wasboxed = ctx.builder.CreateICmpNE(wasboxed, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0)); + setName(ctx.emission_context, wasboxed, "wasboxed"); BasicBlock *currBB = ctx.builder.GetInsertBlock(); @@ -2172,6 +2181,7 @@ static jl_cgval_t convert_julia_type_union(jl_codectx_t &ctx, const jl_cgval_t & }, typ, counter); + setName(ctx.emission_context, union_box_tindex, "union_box_tindex"); if (union_box_dt) { BasicBlock *postBB = BasicBlock::Create(ctx.builder.getContext(), "post_union_isa", ctx.f); ctx.builder.CreateBr(postBB); @@ -2183,6 +2193,7 @@ static jl_cgval_t convert_julia_type_union(jl_codectx_t &ctx, const jl_cgval_t & tindex_phi->addIncoming(new_tindex, currBB); tindex_phi->addIncoming(union_box_tindex, post_union_isaBB); new_tindex = tindex_phi; + setName(ctx.emission_context, new_tindex, "tindex"); } } if (!skip_box.all()) { @@ -2341,6 +2352,21 @@ std::unique_ptr jl_create_llvm_module(StringRef name, LLVMContext &conte return m; } +static void jl_name_jlfunc_args(jl_codegen_params_t ¶ms, Function *F) { + assert(F->arg_size() == 3); + setName(params, F->getArg(0), "function"); + setName(params, F->getArg(1), "args"); + setName(params, F->getArg(2), "nargs"); +} + +static void jl_name_jlfuncparams_args(jl_codegen_params_t ¶ms, Function *F) { + assert(F->arg_size() == 4); + setName(params, F->getArg(0), "function"); + setName(params, F->getArg(1), "args"); + setName(params, F->getArg(2), "nargs"); + setName(params, F->getArg(3), "sparams"); +} + static void jl_init_function(Function *F, const Triple &TT) { // set any attributes that *must* be set on all functions @@ -2822,6 +2848,7 @@ static jl_cgval_t emit_globalref(jl_codectx_t &ctx, jl_module_t *mod, jl_sym_t * if (bnd->constp) return mark_julia_const(ctx, v); LoadInst *v = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, bp, Align(sizeof(void*))); + setName(ctx.emission_context, v, jl_symbol_name(name)); v->setOrdering(order); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_binding); ai.decorateInst(v); @@ -2896,6 +2923,7 @@ static Value *emit_bitsunion_compare(jl_codectx_t &ctx, const jl_cgval_t &arg1, Value *tindex2 = arg2.TIndex; tindex2 = ctx.builder.CreateAnd(tindex2, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x7f)); Value *typeeq = ctx.builder.CreateICmpEQ(tindex, tindex2); + setName(ctx.emission_context, typeeq, "typematch"); tindex = ctx.builder.CreateSelect(typeeq, tindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x00)); BasicBlock *defaultBB = BasicBlock::Create(ctx.builder.getContext(), "unionbits_is_boxed", ctx.f); SwitchInst *switchInst = ctx.builder.CreateSwitch(tindex, defaultBB); @@ -2927,6 +2955,7 @@ static Value *emit_bitsunion_compare(jl_codectx_t &ctx, const jl_cgval_t &arg1, ctx.builder.CreateCall(trap_func); ctx.builder.CreateUnreachable(); ctx.builder.SetInsertPoint(postBB); + setName(ctx.emission_context, phi, "unionbits_is"); return phi; } @@ -3410,14 +3439,16 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, } else { Value *idx_dyn = emit_unbox(ctx, ctx.types().T_size, idx, (jl_value_t*)jl_long_type); - error_unless(ctx, ctx.builder.CreateICmpSGT(idx_dyn, Constant::getNullValue(ctx.types().T_size)), - "arraysize: dimension out of range"); + auto positive = ctx.builder.CreateICmpSGT(idx_dyn, Constant::getNullValue(ctx.types().T_size)); + setName(ctx.emission_context, positive, "ispositive"); + error_unless(ctx, positive, "arraysize: dimension out of range"); BasicBlock *outBB = BasicBlock::Create(ctx.builder.getContext(), "outofrange", ctx.f); BasicBlock *inBB = BasicBlock::Create(ctx.builder.getContext(), "inrange"); BasicBlock *ansBB = BasicBlock::Create(ctx.builder.getContext(), "arraysize"); - ctx.builder.CreateCondBr(ctx.builder.CreateICmpSLE(idx_dyn, - ConstantInt::get(ctx.types().T_size, ndims)), - inBB, outBB); + auto oor = ctx.builder.CreateICmpSLE(idx_dyn, + ConstantInt::get(ctx.types().T_size, ndims)); + setName(ctx.emission_context, oor, "sizeddim"); + ctx.builder.CreateCondBr(oor, inBB, outBB); ctx.builder.SetInsertPoint(outBB); Value *v_one = ConstantInt::get(ctx.types().T_size, 1); ctx.builder.CreateBr(ansBB); @@ -3431,6 +3462,7 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, PHINode *result = ctx.builder.CreatePHI(ctx.types().T_size, 2); result->addIncoming(v_one, outBB); result->addIncoming(v_sz, inBB); + setName(ctx.emission_context, result, "arraysize"); *ret = mark_julia_type(ctx, result, false, jl_long_type); return true; } @@ -3478,17 +3510,25 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, data = emit_bitcast(ctx, data, AT->getPointerTo()); // isbits union selector bytes are stored after a->maxsize Value *ndims = (nd == -1 ? emit_arrayndims(ctx, ary) : ConstantInt::get(getInt16Ty(ctx.builder.getContext()), nd)); + setName(ctx.emission_context, ndims, "ndims"); Value *is_vector = ctx.builder.CreateICmpEQ(ndims, ConstantInt::get(getInt16Ty(ctx.builder.getContext()), 1)); + setName(ctx.emission_context, is_vector, "isvec"); Value *selidx_v = ctx.builder.CreateSub(emit_vectormaxsize(ctx, ary), ctx.builder.CreateZExt(offset, ctx.types().T_size)); + setName(ctx.emission_context, selidx_v, "selidx_v"); Value *selidx_m = emit_arraylen(ctx, ary); Value *selidx = ctx.builder.CreateSelect(is_vector, selidx_v, selidx_m); + setName(ctx.emission_context, selidx, "selidx"); ptindex = ctx.builder.CreateInBoundsGEP(AT, data, selidx); + setName(ctx.emission_context, ptindex, "ptindex"); data = ctx.builder.CreateInBoundsGEP(AT, data, idx); + setName(ctx.emission_context, data, "data"); } ptindex = emit_bitcast(ctx, ptindex, getInt8PtrTy(ctx.builder.getContext())); ptindex = ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), ptindex, offset); ptindex = ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), ptindex, idx); *ret = emit_unionload(ctx, data, ptindex, ety, elsz, al, ctx.tbaa().tbaa_arraybuf, true, union_max, ctx.tbaa().tbaa_arrayselbyte); + if (ret->V) + setName(ctx.emission_context, ret->V, "arrayref"); } else { MDNode *aliasscope = (f == jl_builtin_const_arrayref) ? ctx.noalias().aliasscope.current : nullptr; @@ -3499,6 +3539,8 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, aliasscope, isboxed, AtomicOrdering::NotAtomic); + if (ret->V) + setName(ctx.emission_context, ret->V, "arrayref"); } return true; } @@ -3545,6 +3587,7 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, // the owner of the data is ary itself except if ary->how == 3 flags = ctx.builder.CreateAnd(flags, 3); Value *is_owned = ctx.builder.CreateICmpEQ(flags, ConstantInt::get(getInt16Ty(ctx.builder.getContext()), 3)); + setName(ctx.emission_context, is_owned, "has_owner"); BasicBlock *curBB = ctx.builder.GetInsertBlock(); BasicBlock *ownedBB = BasicBlock::Create(ctx.builder.getContext(), "array_owned", ctx.f); BasicBlock *mergeBB = BasicBlock::Create(ctx.builder.getContext(), "merge_own", ctx.f); @@ -3558,6 +3601,7 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, emit_bitcast(ctx, decay_derived(ctx, aryv), ctx.types().T_pprjlvalue), jl_array_data_owner_offset(nd) / sizeof(jl_value_t*)), Align(sizeof(void*))); + setName(ctx.emission_context, own_ptr, "external_owner"); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); ai.decorateInst(maybe_mark_load_dereferenceable(own_ptr, false, (jl_value_t*)jl_array_any_type)); } @@ -3571,6 +3615,7 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, data_owner = ctx.builder.CreatePHI(ctx.types().T_prjlvalue, 2); data_owner->addIncoming(aryv, curBB); data_owner->addIncoming(own_ptr, ownedBB); + setName(ctx.emission_context, data_owner, "data_owner"); } if (!isboxed && jl_is_uniontype(ety)) { Type *AT = ArrayType::get(IntegerType::get(ctx.builder.getContext(), 8 * al), (elsz + al - 1) / al); @@ -3587,15 +3632,21 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, else { Value *ndims = (nd == -1 ? emit_arrayndims(ctx, ary) : ConstantInt::get(getInt16Ty(ctx.builder.getContext()), nd)); Value *is_vector = ctx.builder.CreateICmpEQ(ndims, ConstantInt::get(getInt16Ty(ctx.builder.getContext()), 1)); + setName(ctx.emission_context, is_vector, "is_vector"); Value *selidx_v = ctx.builder.CreateSub(emit_vectormaxsize(ctx, ary), ctx.builder.CreateZExt(offset, ctx.types().T_size)); + setName(ctx.emission_context, selidx_v, "selidx_v"); Value *selidx_m = emit_arraylen(ctx, ary); Value *selidx = ctx.builder.CreateSelect(is_vector, selidx_v, selidx_m); + setName(ctx.emission_context, selidx, "selidx"); ptindex = ctx.builder.CreateInBoundsGEP(AT, data, selidx); + setName(ctx.emission_context, ptindex, "ptindex"); data = ctx.builder.CreateInBoundsGEP(AT, data, idx); + setName(ctx.emission_context, data, "data"); } ptindex = emit_bitcast(ctx, ptindex, getInt8PtrTy(ctx.builder.getContext())); ptindex = ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), ptindex, offset); ptindex = ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), ptindex, idx); + setName(ctx.emission_context, ptindex, "ptindex"); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_arrayselbyte); ai.decorateInst(ctx.builder.CreateStore(tindex, ptindex)); if (elsz > 0 && (!jl_is_datatype(val.typ) || jl_datatype_size(val.typ) > 0)) { @@ -3694,6 +3745,7 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, idx = emit_bounds_check(ctx, va_ary, NULL, idx, valen, boundscheck); idx = ctx.builder.CreateAdd(idx, ConstantInt::get(ctx.types().T_size, ctx.nReqArgs)); Instruction *v = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue, ctx.argArray, idx), Align(sizeof(void*))); + setName(ctx.emission_context, v, "getfield"); // if we know the result type of this load, we will mark that information here too jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_value); ai.decorateInst(maybe_mark_load_dereferenceable(v, false, rt)); @@ -3862,6 +3914,7 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, Value *fieldtyp_p = ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue, decay_derived(ctx, emit_bitcast(ctx, types_svec, ctx.types().T_pprjlvalue)), idx); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); Value *fieldtyp = ai.decorateInst(ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, fieldtyp_p, Align(sizeof(void*)))); + setName(ctx.emission_context, fieldtyp, "fieldtype"); *ret = mark_julia_type(ctx, fieldtyp, true, (jl_value_t*)jl_type_type); return true; } @@ -3900,6 +3953,7 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, auto rng = MDB.createRange(Constant::getNullValue(ctx.types().T_size), ConstantInt::get(ctx.types().T_size, INTPTR_MAX)); cast(len)->setMetadata(LLVMContext::MD_range, rng); } + setName(ctx.emission_context, len, "sizeof"); *ret = mark_julia_type(ctx, len, false, jl_long_type); return true; } @@ -3914,6 +3968,8 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, elsize = ctx.builder.CreateZExt(emit_arrayelsize(ctx, obj), ctx.types().T_size); } *ret = mark_julia_type(ctx, ctx.builder.CreateMul(len, elsize), false, jl_long_type); + if (ret->V) + setName(ctx.emission_context, ret->V, "sizeof"); return true; } } @@ -4030,6 +4086,7 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, } } Value *isdef = ctx.builder.CreateIsNotNull(fldv); + setName(ctx.emission_context, isdef, "isdefined"); *ret = mark_julia_type(ctx, isdef, false, jl_bool_type); } else { @@ -4131,6 +4188,7 @@ static jl_cgval_t emit_call_specfun_other(jl_codectx_t &ctx, bool is_opaque_clos break; case jl_returninfo_t::Union: result = emit_static_alloca(ctx, ArrayType::get(getInt8Ty(ctx.builder.getContext()), returninfo.union_bytes)); + setName(ctx.emission_context, result, "sret_box"); if (returninfo.union_align > 1) result->setAlignment(Align(returninfo.union_align)); argvals[idx] = result; @@ -4207,6 +4265,7 @@ static jl_cgval_t emit_call_specfun_other(jl_codectx_t &ctx, bool is_opaque_clos } 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*)))); + setName(ctx.emission_context, TheCallee, namep); } CallInst *call = ctx.builder.CreateCall(cft, TheCallee, argvals); call->setAttributes(returninfo.attrs); @@ -4276,6 +4335,7 @@ static jl_cgval_t emit_call_specfun_boxed(jl_codectx_t &ctx, jl_value_t *jlretty } jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); theFptr = ai.decorateInst(ctx.builder.CreateAlignedLoad(pfunc, GV, Align(sizeof(void*)))); + setName(ctx.emission_context, theFptr, namep); } else { theFptr = jl_Module->getOrInsertFunction(specFunctionObject, ctx.types().T_jlfunc).getCallee(); @@ -4574,16 +4634,20 @@ static Value *global_binding_pointer(jl_codectx_t &ctx, jl_module_t *m, jl_sym_t GlobalVariable *bindinggv = new GlobalVariable(*ctx.f->getParent(), ctx.types().T_pjlvalue, false, GlobalVariable::PrivateLinkage, initnul); LoadInst *cachedval = ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, bindinggv, Align(sizeof(void*))); + setName(ctx.emission_context, cachedval, jl_symbol_name(m->name) + StringRef(".") + jl_symbol_name(s) + ".cached"); cachedval->setOrdering(AtomicOrdering::Unordered); BasicBlock *have_val = BasicBlock::Create(ctx.builder.getContext(), "found"); BasicBlock *not_found = BasicBlock::Create(ctx.builder.getContext(), "notfound"); BasicBlock *currentbb = ctx.builder.GetInsertBlock(); - ctx.builder.CreateCondBr(ctx.builder.CreateICmpNE(cachedval, initnul), have_val, not_found); + auto iscached = ctx.builder.CreateICmpNE(cachedval, initnul); + setName(ctx.emission_context, iscached, "iscached"); + ctx.builder.CreateCondBr(iscached, have_val, not_found); ctx.f->getBasicBlockList().push_back(not_found); ctx.builder.SetInsertPoint(not_found); Value *bval = ctx.builder.CreateCall(prepare_call(assign ? jlgetbindingwrorerror_func : jlgetbindingorerror_func), { literal_pointer_val(ctx, (jl_value_t*)m), literal_pointer_val(ctx, (jl_value_t*)s) }); + setName(ctx.emission_context, bval, jl_symbol_name(m->name) + StringRef(".") + jl_symbol_name(s) + ".found"); ctx.builder.CreateAlignedStore(bval, bindinggv, Align(sizeof(void*)))->setOrdering(AtomicOrdering::Release); ctx.builder.CreateBr(have_val); ctx.f->getBasicBlockList().push_back(have_val); @@ -4591,6 +4655,7 @@ static Value *global_binding_pointer(jl_codectx_t &ctx, jl_module_t *m, jl_sym_t PHINode *p = ctx.builder.CreatePHI(ctx.types().T_pjlvalue, 2); p->addIncoming(cachedval, currentbb); p->addIncoming(bval, not_found); + setName(ctx.emission_context, p, jl_symbol_name(m->name) + StringRef(".") + jl_symbol_name(s)); return p; } if (assign) { @@ -4614,6 +4679,7 @@ static Value *global_binding_pointer(jl_codectx_t &ctx, jl_module_t *m, jl_sym_t static jl_cgval_t emit_checked_var(jl_codectx_t &ctx, Value *bp, jl_sym_t *name, bool isvol, MDNode *tbaa) { LoadInst *v = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, bp, Align(sizeof(void*))); + setName(ctx.emission_context, v, jl_symbol_name(name) + StringRef(".checked")); if (isvol) v->setVolatile(true); v->setOrdering(AtomicOrdering::Unordered); @@ -4640,6 +4706,7 @@ static jl_cgval_t emit_sparam(jl_codectx_t &ctx, size_t i) i + sizeof(jl_svec_t) / sizeof(jl_value_t*)); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); Value *sp = ai.decorateInst(ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, bp, Align(sizeof(void*)))); + setName(ctx.emission_context, sp, "sparam"); Value *isnull = ctx.builder.CreateICmpNE(emit_typeof(ctx, sp, false, true), emit_tagfrom(ctx, jl_tvar_type)); jl_unionall_t *sparam = (jl_unionall_t*)ctx.linfo->def.method->sig; for (size_t j = 0; j < i; j++) { @@ -4745,9 +4812,11 @@ static jl_cgval_t emit_varinfo(jl_codectx_t &ctx, jl_varinfo_t &vi, jl_sym_t *va else { // copy value to a non-mutable (non-volatile SSA) location AllocaInst *varslot = cast(vi.value.V); + setName(ctx.emission_context, varslot, jl_symbol_name(varname)); Type *T = varslot->getAllocatedType(); assert(!varslot->isArrayAllocation() && "variables not expected to be VLA"); AllocaInst *ssaslot = cast(varslot->clone()); + setName(ctx.emission_context, ssaslot, jl_symbol_name(varname) + StringRef(".ssa")); ssaslot->insertAfter(varslot); if (vi.isVolatile) { Value *unbox = ctx.builder.CreateAlignedLoad(ssaslot->getAllocatedType(), varslot, @@ -4800,8 +4869,10 @@ static jl_cgval_t emit_varinfo(jl_codectx_t &ctx, jl_varinfo_t &vi, jl_sym_t *va isnull = box_isnull; } } - if (isnull) + if (isnull) { + setName(ctx.emission_context, isnull, jl_symbol_name(varname) + StringRef("_is_null")); undef_var_error_ifnot(ctx, isnull, varname); + } return v; } @@ -5270,6 +5341,7 @@ static std::pair get_oc_function(jl_codectx_t &ctx, jl_met Function::ExternalLinkage, fname, jl_Module); jl_init_function(F, ctx.emission_context.TargetTriple); + jl_name_jlfunc_args(ctx.emission_context, F); F->setAttributes(AttributeList::get(ctx.builder.getContext(), {get_func_attrs(ctx.builder.getContext()), F->getAttributes()})); } Function *specF = NULL; @@ -5742,6 +5814,7 @@ static Function *emit_tojlinvoke(jl_code_instance_t *codeinst, Module *M, jl_cod GlobalVariable::InternalLinkage, name, M); jl_init_function(f, params.TargetTriple); + jl_name_jlfunc_args(params, f); //f->setAlwaysInline(); ctx.f = f; // for jl_Module BasicBlock *b0 = BasicBlock::Create(ctx.builder.getContext(), "top", f); @@ -6230,6 +6303,7 @@ static Function* gen_cfun_wrapper( theFptr = Function::Create(ctx.types().T_jlfunc, GlobalVariable::ExternalLinkage, fname, jl_Module); jl_init_function(theFptr, ctx.emission_context.TargetTriple); + jl_name_jlfunc_args(ctx.emission_context, theFptr); addRetAttr(theFptr, Attribute::NonNull); } else { @@ -6284,9 +6358,11 @@ static Function* gen_cfun_wrapper( else { if (jlfunc_sret) { result = emit_static_alloca(ctx, getAttributeAtIndex(returninfo.attrs, 1, Attribute::StructRet).getValueAsType()); + setName(ctx.emission_context, result, "sret"); assert(cast(result->getType())->hasSameElementTypeAs(cast(cft->getParamType(0)))); } else { result = emit_static_alloca(ctx, get_unionbytes_type(ctx.builder.getContext(), returninfo.union_bytes)); + setName(ctx.emission_context, result, "result_union"); assert(cast(result->getType())->hasSameElementTypeAs(cast(cft->getParamType(0)))); } } @@ -6294,6 +6370,7 @@ static Function* gen_cfun_wrapper( } if (returninfo.return_roots) { AllocaInst *return_roots = emit_static_alloca(ctx, get_returnroots_type(ctx, returninfo.return_roots)); + setName(ctx.emission_context, return_roots, "return_roots"); args.push_back(return_roots); } if (gcstack_arg) @@ -6433,6 +6510,8 @@ static Function* gen_cfun_wrapper( GlobalVariable::ExternalLinkage, funcName, M); jl_init_function(cw_make, ctx.emission_context.TargetTriple); + cw_make->getArg(0)->setName("wrapper"); + cw_make->getArg(1)->setName("newval"); BasicBlock *b0 = BasicBlock::Create(ctx.builder.getContext(), "top", cw_make); IRBuilder<> cwbuilder(b0); Function::arg_iterator AI = cw_make->arg_begin(); @@ -6596,6 +6675,7 @@ static jl_cgval_t emit_cfunction(jl_codectx_t &ctx, jl_value_t *output_type, con if (outboxed) { assert(jl_datatype_size(output_type) == sizeof(void*) * 4); Value *strct = emit_allocobj(ctx, (jl_datatype_t*)output_type); + setName(ctx.emission_context, strct, "cfun_result"); Value *derived_strct = emit_bitcast(ctx, decay_derived(ctx, strct), ctx.types().T_size->getPointerTo()); MDNode *tbaa = best_tbaa(ctx.tbaa(), output_type); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); @@ -6674,6 +6754,7 @@ static Function *gen_invoke_wrapper(jl_method_instance_t *lam, jl_value_t *jlret ++GeneratedInvokeWrappers; Function *w = Function::Create(get_func_sig(M->getContext()), GlobalVariable::ExternalLinkage, funcName, M); jl_init_function(w, params.TargetTriple); + jl_name_jlfunc_args(params, w); w->setAttributes(AttributeList::get(M->getContext(), {get_func_attrs(M->getContext()), w->getAttributes()})); w->addFnAttr(Attribute::OptimizeNone); w->addFnAttr(Attribute::NoInline); @@ -6710,6 +6791,7 @@ static Function *gen_invoke_wrapper(jl_method_instance_t *lam, jl_value_t *jlret case jl_returninfo_t::SRet: assert(cast(ftype->getParamType(0))->isOpaqueOrPointeeTypeMatches(getAttributeAtIndex(f.attrs, 1, Attribute::StructRet).getValueAsType())); result = ctx.builder.CreateAlloca(getAttributeAtIndex(f.attrs, 1, Attribute::StructRet).getValueAsType()); + setName(ctx.emission_context, result, "sret"); args[idx] = result; idx++; break; @@ -6719,10 +6801,12 @@ static Function *gen_invoke_wrapper(jl_method_instance_t *lam, jl_value_t *jlret result->setAlignment(Align(f.union_align)); args[idx] = result; idx++; + setName(ctx.emission_context, result, "result_union"); break; } if (f.return_roots) { AllocaInst *return_roots = emit_static_alloca(ctx, ArrayType::get(ctx.types().T_prjlvalue, f.return_roots)); + setName(ctx.emission_context, return_roots, "return_roots"); args[idx] = return_roots; idx++; } @@ -7108,11 +7192,9 @@ static jl_llvm_functions_t // jl_printf(JL_STDERR, "\n*** compiling %s at %s:%d\n\n", // jl_symbol_name(ctx.name), ctx.file.str().c_str(), toplineno); - ctx.debug_enabled = true; + bool debug_enabled = ctx.emission_context.debug_level != 0; if (dbgFuncName.empty()) // Should never happen anymore? - ctx.debug_enabled = 0; - if (jl_options.debug_level == 0) - ctx.debug_enabled = 0; + debug_enabled = false; // step 2. process var-info lists to see what vars need boxing int n_ssavalues = jl_is_long(src->ssavaluetypes) ? jl_unbox_long(src->ssavaluetypes) : jl_array_len(src->ssavaluetypes); @@ -7236,6 +7318,11 @@ static jl_llvm_functions_t GlobalVariable::ExternalLinkage, declarations.specFunctionObject, M); jl_init_function(f, ctx.emission_context.TargetTriple); + if (needsparams) { + jl_name_jlfuncparams_args(ctx.emission_context, f); + } else { + jl_name_jlfunc_args(ctx.emission_context, f); + } f->setAttributes(AttributeList::get(ctx.builder.getContext(), {get_func_attrs(ctx.builder.getContext()), f->getAttributes()})); returninfo.decl = f; declarations.functionObject = needsparams ? "jl_fptr_sparam" : "jl_fptr_args"; @@ -7281,14 +7368,14 @@ static jl_llvm_functions_t tableKind = DICompileUnit::DebugNameTableKind::GNU; else tableKind = DICompileUnit::DebugNameTableKind::None; - DIBuilder dbuilder(*M, true, ctx.debug_enabled ? getOrCreateJuliaCU(*M, emissionKind, tableKind) : NULL); + DIBuilder dbuilder(*M, true, debug_enabled ? getOrCreateJuliaCU(*M, emissionKind, tableKind) : NULL); DIFile *topfile = NULL; DISubprogram *SP = NULL; DebugLoc noDbg, topdebugloc; - if (ctx.debug_enabled) { + if (debug_enabled) { topfile = dbuilder.createFile(ctx.file, "."); DISubroutineType *subrty; - if (jl_options.debug_level <= 1) + if (ctx.emission_context.debug_level <= 1) subrty = debuginfo.jl_di_func_null_sig; else if (!specsig) subrty = debuginfo.jl_di_func_sig; @@ -7309,7 +7396,7 @@ static jl_llvm_functions_t ); topdebugloc = DILocation::get(ctx.builder.getContext(), toplineno, 0, SP, NULL); f->setSubprogram(SP); - if (jl_options.debug_level >= 2) { + if (ctx.emission_context.debug_level >= 2) { const bool AlwaysPreserve = true; // Go over all arguments and local variables and initialize their debug information for (i = 0; i < nreq; i++) { @@ -7371,6 +7458,7 @@ static jl_llvm_functions_t fArg = &*AI++; argArray = &*AI++; pargArray = ctx.builder.CreateAlloca(argArray->getType()); + setName(ctx.emission_context, pargArray, "stackargs"); ctx.builder.CreateStore(argArray, pargArray, true/*volatile store to prevent removal of this alloca*/); argCount = &*AI++; ctx.argArray = argArray; @@ -7412,6 +7500,7 @@ static jl_llvm_functions_t lv->setName(jl_symbol_name(s)); varinfo.value = mark_julia_slot(lv, jt, NULL, ctx.tbaa().tbaa_stack); varinfo.pTIndex = emit_static_alloca(ctx, getInt8Ty(ctx.builder.getContext())); + setName(ctx.emission_context, varinfo.pTIndex, "tindex"); } else if (allunbox) { // all ghost values just need a selector allocated @@ -7438,7 +7527,7 @@ static jl_llvm_functions_t } varinfo.value = mark_julia_slot(lv, jt, NULL, ctx.tbaa().tbaa_stack); alloc_def_flag(ctx, varinfo); - if (ctx.debug_enabled && varinfo.dinfo) { + if (debug_enabled && varinfo.dinfo) { assert((Metadata*)varinfo.dinfo->getType() != debuginfo.jl_pvalue_dillvmt); dbuilder.insertDeclare(lv, varinfo.dinfo, dbuilder.createExpression(), topdebugloc, @@ -7455,7 +7544,7 @@ static jl_llvm_functions_t StoreInst *SI = new StoreInst(Constant::getNullValue(ctx.types().T_prjlvalue), av, false, Align(sizeof(void*))); SI->insertAfter(ctx.topalloca); varinfo.boxroot = av; - if (ctx.debug_enabled && varinfo.dinfo) { + if (debug_enabled && varinfo.dinfo) { DIExpression *expr; if ((Metadata*)varinfo.dinfo->getType() == debuginfo.jl_pvalue_dillvmt) { expr = dbuilder.createExpression(); @@ -7656,7 +7745,7 @@ static jl_llvm_functions_t ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, argPtr, Align(sizeof(void*))), false, vi.value.typ)); theArg = mark_julia_type(ctx, load, true, vi.value.typ); - if (ctx.debug_enabled && vi.dinfo && !vi.boxroot && !vi.value.V) { + if (debug_enabled && vi.dinfo && !vi.boxroot && !vi.value.V) { SmallVector addr; addr.push_back(llvm::dwarf::DW_OP_deref); addr.push_back(llvm::dwarf::DW_OP_plus_uconst); @@ -7675,7 +7764,7 @@ static jl_llvm_functions_t assert(vi.value.V == NULL && "unexpected variable slot created for argument"); // keep track of original (possibly boxed) value to avoid re-boxing or moving vi.value = theArg; - if (specsig && theArg.V && ctx.debug_enabled && vi.dinfo) { + if (specsig && theArg.V && debug_enabled && vi.dinfo) { SmallVector addr; Value *parg; if (theArg.ispointer()) { @@ -7801,7 +7890,7 @@ static jl_llvm_functions_t else info.is_user_code = in_user_mod(module); info.is_tracked = in_tracked_path(info.file); - if (ctx.debug_enabled) { + if (debug_enabled) { StringRef fname; if (jl_is_method_instance(method)) method = ((jl_method_instance_t*)method)->def.value; @@ -8042,7 +8131,7 @@ static jl_llvm_functions_t while (cursor != -1) { int32_t debuginfoloc = ((int32_t*)jl_array_data(src->codelocs))[cursor]; if (debuginfoloc > 0) { - if (ctx.debug_enabled) + if (debug_enabled) ctx.builder.SetCurrentDebugLocation(linetable.at(debuginfoloc).loc); coverageVisitStmt(debuginfoloc); } @@ -8444,7 +8533,7 @@ static jl_llvm_functions_t for (auto &I : BB) { CallBase *call = dyn_cast(&I); if (call) { - if (ctx.debug_enabled && !I.getDebugLoc()) { + if (debug_enabled && !I.getDebugLoc()) { // LLVM Verifier: inlinable function call in a function with debug info must have a !dbg location // make sure that anything we attempt to call has some inlining info, just in case optimization messed up // (except if we know that it is an intrinsic used in our prologue, which should never have its own debug subprogram) @@ -8469,7 +8558,7 @@ static jl_llvm_functions_t in_prologue = false; } } - if (ctx.debug_enabled) + if (debug_enabled) dbuilder.finalize(); if (ctx.vaSlot > 0) { @@ -8665,6 +8754,7 @@ jl_llvm_functions_t jl_emit_codeinst( if (// keep code when keeping everything !(JL_DELETE_NON_INLINEABLE) || // aggressively keep code when debugging level >= 2 + // note that this uses the global jl_options.debug_level, not the local emission_ctx.debug_level jl_options.debug_level > 1) { // update the stored code if (inferred != (jl_value_t*)src) { diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index ee1ded5a51e44..09e04eb683af1 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -345,12 +345,14 @@ static Value *emit_unboxed_coercion(jl_codectx_t &ctx, Type *to, Value *unboxed) else if (!ty->isIntOrPtrTy() && !ty->isFloatingPointTy()) { assert(DL.getTypeSizeInBits(ty) == DL.getTypeSizeInBits(to)); AllocaInst *cast = ctx.builder.CreateAlloca(ty); + setName(ctx.emission_context, cast, "coercion"); ctx.builder.CreateStore(unboxed, cast); unboxed = ctx.builder.CreateLoad(to, ctx.builder.CreateBitCast(cast, to->getPointerTo())); } else if (frompointer) { Type *INTT_to = INTT(to, DL); unboxed = ctx.builder.CreatePtrToInt(unboxed, INTT_to); + setName(ctx.emission_context, unboxed, "coercion"); if (INTT_to != to) unboxed = ctx.builder.CreateBitCast(unboxed, to); } @@ -359,6 +361,7 @@ static Value *emit_unboxed_coercion(jl_codectx_t &ctx, Type *to, Value *unboxed) if (to != INTT_to) unboxed = ctx.builder.CreateBitCast(unboxed, INTT_to); unboxed = emit_inttoptr(ctx, unboxed, to); + setName(ctx.emission_context, unboxed, "coercion"); } else { unboxed = ctx.builder.CreateBitCast(unboxed, to); @@ -394,6 +397,7 @@ static Value *emit_unbox(jl_codectx_t &ctx, Type *to, const jl_cgval_t &x, jl_va if (jt == (jl_value_t*)jl_bool_type || to->isIntegerTy(1)) { jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, x.tbaa); Instruction *unbox_load = ai.decorateInst(ctx.builder.CreateLoad(getInt8Ty(ctx.builder.getContext()), maybe_bitcast(ctx, p, getInt8PtrTy(ctx.builder.getContext())))); + setName(ctx.emission_context, unbox_load, "unbox"); if (jt == (jl_value_t*)jl_bool_type) unbox_load->setMetadata(LLVMContext::MD_range, MDNode::get(ctx.builder.getContext(), { ConstantAsMetadata::get(ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0)), @@ -421,12 +425,14 @@ static Value *emit_unbox(jl_codectx_t &ctx, Type *to, const jl_cgval_t &x, jl_va (to->isFloatingPointTy() || to->isIntegerTy() || to->isPointerTy()) && DL.getTypeSizeInBits(AllocType) == DL.getTypeSizeInBits(to)) { Instruction *load = ctx.builder.CreateAlignedLoad(AllocType, p, Align(alignment)); + setName(ctx.emission_context, load, "unbox"); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, x.tbaa); return emit_unboxed_coercion(ctx, to, ai.decorateInst(load)); } } p = maybe_bitcast(ctx, p, ptype); Instruction *load = ctx.builder.CreateAlignedLoad(to, p, Align(alignment)); + setName(ctx.emission_context, load, "unbox"); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, x.tbaa); return ai.decorateInst(load); } @@ -531,8 +537,10 @@ static jl_cgval_t generic_bitcast(jl_codectx_t &ctx, const jl_cgval_t *argv) } else { Value *size = emit_datatype_size(ctx, typ); + auto sizecheck = ctx.builder.CreateICmpEQ(size, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), nb)); + setName(ctx.emission_context, sizecheck, "sizecheck"); error_unless(ctx, - ctx.builder.CreateICmpEQ(size, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), nb)), + sizecheck, "bitcast: argument size does not match size of target type"); } } @@ -555,20 +563,25 @@ static jl_cgval_t generic_bitcast(jl_codectx_t &ctx, const jl_cgval_t *argv) storage_type, emit_bitcast(ctx, data_pointer(ctx, v), storage_type->getPointerTo()))); + setName(ctx.emission_context, vx, "bitcast"); } vxt = vx->getType(); if (vxt != llvmt) { - if (llvmt->isIntegerTy(1)) + if (llvmt->isIntegerTy(1)) { vx = ctx.builder.CreateTrunc(vx, llvmt); - else if (vxt->isIntegerTy(1) && llvmt->isIntegerTy(8)) + } else if (vxt->isIntegerTy(1) && llvmt->isIntegerTy(8)) { vx = ctx.builder.CreateZExt(vx, llvmt); - else if (vxt->isPointerTy() && !llvmt->isPointerTy()) + } else if (vxt->isPointerTy() && !llvmt->isPointerTy()) { vx = ctx.builder.CreatePtrToInt(vx, llvmt); - else if (!vxt->isPointerTy() && llvmt->isPointerTy()) + setName(ctx.emission_context, vx, "bitcast_coercion"); + } else if (!vxt->isPointerTy() && llvmt->isPointerTy()) { vx = emit_inttoptr(ctx, vx, llvmt); - else + setName(ctx.emission_context, vx, "bitcast_coercion"); + } else { vx = emit_bitcast(ctx, vx, llvmt); + setName(ctx.emission_context, vx, "bitcast_coercion"); + } } if (jl_is_concrete_type((jl_value_t*)bt)) { @@ -576,6 +589,7 @@ static jl_cgval_t generic_bitcast(jl_codectx_t &ctx, const jl_cgval_t *argv) } else { Value *box = emit_allocobj(ctx, nb, bt_value_rt); + setName(ctx.emission_context, box, "bitcast_box"); init_bits_value(ctx, box, vx, ctx.tbaa().tbaa_immut); return mark_julia_type(ctx, box, true, bt->name->wrapper); } @@ -618,8 +632,10 @@ static jl_cgval_t generic_cast( // but if we start looking at more bits we need to actually do the // rounding first instead of carrying around incorrect low bits. Value *jlfloattemp_var = emit_static_alloca(ctx, from->getType()); + setName(ctx.emission_context, jlfloattemp_var, "rounding_slot"); ctx.builder.CreateStore(from, jlfloattemp_var); from = ctx.builder.CreateLoad(from->getType(), jlfloattemp_var, /*force this to load from the stack*/true); + setName(ctx.emission_context, from, "rounded"); } } Value *ans = ctx.builder.CreateCast(Op, from, to); @@ -632,6 +648,7 @@ static jl_cgval_t generic_cast( Value *targ_rt = boxed(ctx, targ); emit_concretecheck(ctx, targ_rt, std::string(jl_intrinsic_name(f)) + ": target type not a leaf primitive type"); Value *box = emit_allocobj(ctx, nb, targ_rt); + setName(ctx.emission_context, box, "cast_box"); init_bits_value(ctx, box, ans, ctx.tbaa().tbaa_immut); return mark_julia_type(ctx, box, true, jlto->name->wrapper); } @@ -667,10 +684,13 @@ static jl_cgval_t emit_pointerref(jl_codectx_t &ctx, jl_cgval_t *argv) Value *idx = emit_unbox(ctx, ctx.types().T_size, i, (jl_value_t*)jl_long_type); Value *im1 = ctx.builder.CreateSub(idx, ConstantInt::get(ctx.types().T_size, 1)); + setName(ctx.emission_context, im1, "pointerref_idx"); if (ety == (jl_value_t*)jl_any_type) { Value *thePtr = emit_unbox(ctx, ctx.types().T_pprjlvalue, e, e.typ); + setName(ctx.emission_context, thePtr, "unbox_any_ptr"); LoadInst *load = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue, thePtr, im1), Align(align_nb)); + setName(ctx.emission_context, load, "any_unbox"); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_data); ai.decorateInst(load); return mark_julia_type(ctx, load, true, ety); @@ -679,10 +699,13 @@ static jl_cgval_t emit_pointerref(jl_codectx_t &ctx, jl_cgval_t *argv) assert(jl_is_datatype(ety)); uint64_t size = jl_datatype_size(ety); Value *strct = emit_allocobj(ctx, (jl_datatype_t*)ety); + setName(ctx.emission_context, strct, "pointerref_box"); im1 = ctx.builder.CreateMul(im1, ConstantInt::get(ctx.types().T_size, LLT_ALIGN(size, jl_datatype_align(ety)))); + setName(ctx.emission_context, im1, "pointerref_offset"); Value *thePtr = emit_unbox(ctx, getInt8PtrTy(ctx.builder.getContext()), e, e.typ); thePtr = ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), emit_bitcast(ctx, thePtr, getInt8PtrTy(ctx.builder.getContext())), im1); + setName(ctx.emission_context, thePtr, "pointerref_src"); MDNode *tbaa = best_tbaa(ctx.tbaa(), ety); emit_memcpy(ctx, strct, jl_aliasinfo_t::fromTBAA(ctx, tbaa), thePtr, jl_aliasinfo_t::fromTBAA(ctx, nullptr), size, 1); return mark_julia_type(ctx, strct, true, ety); @@ -693,7 +716,9 @@ static jl_cgval_t emit_pointerref(jl_codectx_t &ctx, jl_cgval_t *argv) assert(!isboxed); if (!type_is_ghost(ptrty)) { Value *thePtr = emit_unbox(ctx, ptrty->getPointerTo(), e, e.typ); - return typed_load(ctx, thePtr, im1, ety, ctx.tbaa().tbaa_data, nullptr, isboxed, AtomicOrdering::NotAtomic, true, align_nb); + auto load = typed_load(ctx, thePtr, im1, ety, ctx.tbaa().tbaa_data, nullptr, isboxed, AtomicOrdering::NotAtomic, true, align_nb); + setName(ctx.emission_context, load.V, "pointerref"); + return load; } else { return ghostValue(ctx, ety); @@ -736,14 +761,17 @@ static jl_cgval_t emit_pointerset(jl_codectx_t &ctx, jl_cgval_t *argv) Value *idx = emit_unbox(ctx, ctx.types().T_size, i, (jl_value_t*)jl_long_type); Value *im1 = ctx.builder.CreateSub(idx, ConstantInt::get(ctx.types().T_size, 1)); + setName(ctx.emission_context, im1, "pointerset_idx"); Value *thePtr; if (ety == (jl_value_t*)jl_any_type) { // unsafe_store to Ptr{Any} is allowed to implicitly drop GC roots. thePtr = emit_unbox(ctx, ctx.types().T_size->getPointerTo(), e, e.typ); - Instruction *store = ctx.builder.CreateAlignedStore( - ctx.builder.CreatePtrToInt(emit_pointer_from_objref(ctx, boxed(ctx, x)), ctx.types().T_size), - ctx.builder.CreateInBoundsGEP(ctx.types().T_size, thePtr, im1), Align(align_nb)); + auto gep = ctx.builder.CreateInBoundsGEP(ctx.types().T_size, thePtr, im1); + setName(ctx.emission_context, gep, "pointerset_ptr"); + auto val = ctx.builder.CreatePtrToInt(emit_pointer_from_objref(ctx, boxed(ctx, x)), ctx.types().T_size); + setName(ctx.emission_context, val, "pointerset_val"); + Instruction *store = ctx.builder.CreateAlignedStore(val, gep, Align(align_nb)); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_data); ai.decorateInst(store); } @@ -752,7 +780,10 @@ static jl_cgval_t emit_pointerset(jl_codectx_t &ctx, jl_cgval_t *argv) uint64_t size = jl_datatype_size(ety); im1 = ctx.builder.CreateMul(im1, ConstantInt::get(ctx.types().T_size, LLT_ALIGN(size, jl_datatype_align(ety)))); - emit_memcpy(ctx, ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), thePtr, im1), jl_aliasinfo_t::fromTBAA(ctx, nullptr), x, size, align_nb); + setName(ctx.emission_context, im1, "pointerset_offset"); + auto gep = ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), thePtr, im1); + setName(ctx.emission_context, gep, "pointerset_ptr"); + emit_memcpy(ctx, gep, jl_aliasinfo_t::fromTBAA(ctx, nullptr), x, size, align_nb); } else { bool isboxed; @@ -803,6 +834,7 @@ static jl_cgval_t emit_atomic_pointerref(jl_codectx_t &ctx, jl_cgval_t *argv) if (ety == (jl_value_t*)jl_any_type) { Value *thePtr = emit_unbox(ctx, ctx.types().T_pprjlvalue, e, e.typ); LoadInst *load = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, thePtr, Align(sizeof(jl_value_t*))); + setName(ctx.emission_context, load, "atomic_pointerref"); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_data); ai.decorateInst(load); load->setOrdering(llvm_order); @@ -823,11 +855,13 @@ static jl_cgval_t emit_atomic_pointerref(jl_codectx_t &ctx, jl_cgval_t *argv) if (!jl_isbits(ety)) { assert(jl_is_datatype(ety)); Value *strct = emit_allocobj(ctx, (jl_datatype_t*)ety); + setName(ctx.emission_context, strct, "atomic_pointerref_box"); Value *thePtr = emit_unbox(ctx, getInt8PtrTy(ctx.builder.getContext()), e, e.typ); Type *loadT = Type::getIntNTy(ctx.builder.getContext(), nb * 8); thePtr = emit_bitcast(ctx, thePtr, loadT->getPointerTo()); MDNode *tbaa = best_tbaa(ctx.tbaa(), ety); LoadInst *load = ctx.builder.CreateAlignedLoad(loadT, thePtr, Align(nb)); + setName(ctx.emission_context, load, "atomic_pointerref"); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); ai.decorateInst(load); load->setOrdering(llvm_order); @@ -842,7 +876,9 @@ static jl_cgval_t emit_atomic_pointerref(jl_codectx_t &ctx, jl_cgval_t *argv) assert(!isboxed); if (!type_is_ghost(ptrty)) { Value *thePtr = emit_unbox(ctx, ptrty->getPointerTo(), e, e.typ); - return typed_load(ctx, thePtr, nullptr, ety, ctx.tbaa().tbaa_data, nullptr, isboxed, llvm_order, true, nb); + auto load = typed_load(ctx, thePtr, nullptr, ety, ctx.tbaa().tbaa_data, nullptr, isboxed, llvm_order, true, nb); + setName(ctx.emission_context, load.V, "atomic_pointerref"); + return load; } else { if (order > jl_memory_order_monotonic) @@ -942,15 +978,18 @@ static jl_cgval_t emit_atomic_pointerop(jl_codectx_t &ctx, intrinsic f, const jl static Value *emit_checked_srem_int(jl_codectx_t &ctx, Value *x, Value *den) { Type *t = den->getType(); + auto ndivby0 = ctx.builder.CreateICmpNE(den, ConstantInt::get(t, 0)); + setName(ctx.emission_context, ndivby0, "ndivby0"); raise_exception_unless(ctx, - ctx.builder.CreateICmpNE(den, ConstantInt::get(t, 0)), + ndivby0, literal_pointer_val(ctx, jl_diverror_exception)); BasicBlock *m1BB = BasicBlock::Create(ctx.builder.getContext(), "minus1", ctx.f); BasicBlock *okBB = BasicBlock::Create(ctx.builder.getContext(), "oksrem", ctx.f); BasicBlock *cont = BasicBlock::Create(ctx.builder.getContext(), "after_srem", ctx.f); PHINode *ret = PHINode::Create(t, 2); - ctx.builder.CreateCondBr(ctx.builder.CreateICmpEQ(den ,ConstantInt::get(t, -1, true)), - m1BB, okBB); + auto divbym1 = ctx.builder.CreateICmpEQ(den, ConstantInt::get(t, -1, true)); + setName(ctx.emission_context, divbym1, "divbym1"); + ctx.builder.CreateCondBr(divbym1, m1BB, okBB); ctx.builder.SetInsertPoint(m1BB); ctx.builder.CreateBr(cont); ctx.builder.SetInsertPoint(okBB); @@ -960,6 +999,7 @@ static Value *emit_checked_srem_int(jl_codectx_t &ctx, Value *x, Value *den) ret->addIncoming(// rem(typemin, -1) is undefined ConstantInt::get(t, 0), m1BB); ret->addIncoming(sremval, okBB); + setName(ctx.emission_context, ret, "checked_srem"); ctx.builder.Insert(ret); return ret; } @@ -995,6 +1035,7 @@ static Value *emit_untyped_intrinsic(jl_codectx_t &ctx, intrinsic f, Value **arg static jl_cgval_t emit_ifelse(jl_codectx_t &ctx, jl_cgval_t c, jl_cgval_t x, jl_cgval_t y, jl_value_t *rt_hint) { Value *isfalse = emit_condition(ctx, c, "ifelse"); + setName(ctx.emission_context, isfalse, "ifelse_cond"); jl_value_t *t1 = x.typ; jl_value_t *t2 = y.typ; // handle cases where the condition is irrelevant based on type info @@ -1067,6 +1108,7 @@ static jl_cgval_t emit_ifelse(jl_codectx_t &ctx, jl_cgval_t c, jl_cgval_t x, jl_ if (x_ptr->getType() != y_ptr->getType()) y_ptr = ctx.builder.CreateBitCast(y_ptr, x_ptr->getType()); ifelse_result = ctx.builder.CreateSelect(isfalse, y_ptr, x_ptr); + setName(ctx.emission_context, ifelse_result, "ifelse_result"); ifelse_tbaa = MDNode::getMostGenericTBAA(x.tbaa, y.tbaa); if (ifelse_tbaa == NULL) { // LLVM won't return a TBAA result for the root, but mark_julia_struct requires it: make it now @@ -1111,6 +1153,7 @@ static jl_cgval_t emit_ifelse(jl_codectx_t &ctx, jl_cgval_t c, jl_cgval_t x, jl_ ctx.builder.SetInsertPoint(post); ctx.builder.Insert(ret); tindex = ret; + setName(ctx.emission_context, tindex, "ifelse_tindex"); } jl_cgval_t ret = mark_julia_slot(ifelse_result, rt_hint, tindex, ifelse_tbaa); if (x_vboxed || y_vboxed) { @@ -1119,6 +1162,7 @@ static jl_cgval_t emit_ifelse(jl_codectx_t &ctx, jl_cgval_t c, jl_cgval_t x, jl_ if (!y_vboxed) y_vboxed = ConstantPointerNull::get(cast(x_vboxed->getType())); ret.Vboxed = ctx.builder.CreateSelect(isfalse, y_vboxed, x_vboxed); + setName(ctx.emission_context, ret.Vboxed, "ifelse_vboxed"); assert(ret.Vboxed->getType() == ctx.types().T_prjlvalue); } return ret; @@ -1126,6 +1170,7 @@ static jl_cgval_t emit_ifelse(jl_codectx_t &ctx, jl_cgval_t c, jl_cgval_t x, jl_ ifelse_result = ctx.builder.CreateSelect(isfalse, boxed(ctx, y), boxed(ctx, x)); + setName(ctx.emission_context, ifelse_result, "ifelse_result"); } jl_value_t *jt = (t1 == t2 ? t1 : rt_hint); return mark_julia_type(ctx, ifelse_result, isboxed, jt); @@ -1411,7 +1456,9 @@ static Value *emit_untyped_intrinsic(jl_codectx_t &ctx, intrinsic f, Value **arg FunctionCallee intr = Intrinsic::getDeclaration(jl_Module, intr_id, makeArrayRef(t)); Value *res = ctx.builder.CreateCall(intr, {x, y}); Value *val = ctx.builder.CreateExtractValue(res, ArrayRef(0)); + setName(ctx.emission_context, val, "checked"); Value *obit = ctx.builder.CreateExtractValue(res, ArrayRef(1)); + setName(ctx.emission_context, obit, "overflow"); Value *obyte = ctx.builder.CreateZExt(obit, getInt8Ty(ctx.builder.getContext())); jl_value_t *params[2]; @@ -1429,30 +1476,31 @@ static Value *emit_untyped_intrinsic(jl_codectx_t &ctx, intrinsic f, Value **arg case checked_sdiv_int: { Value *typemin = ctx.builder.CreateShl(ConstantInt::get(t, 1), t->getPrimitiveSizeInBits() - 1); - raise_exception_unless(ctx, - ctx.builder.CreateAnd( - ctx.builder.CreateICmpNE(y, ConstantInt::get(t, 0)), - ctx.builder.CreateOr( - ctx.builder.CreateICmpNE(y, ConstantInt::get(t, -1, true)), - ctx.builder.CreateICmpNE(x, typemin))), - literal_pointer_val(ctx, jl_diverror_exception)); + auto cond = ctx.builder.CreateAnd( + ctx.builder.CreateICmpNE(y, ConstantInt::get(t, 0)), + ctx.builder.CreateOr( + ctx.builder.CreateICmpNE(y, ConstantInt::get(t, -1, true)), + ctx.builder.CreateICmpNE(x, typemin))); + setName(ctx.emission_context, cond, "divisor_valid"); + raise_exception_unless(ctx, cond, literal_pointer_val(ctx, jl_diverror_exception)); return ctx.builder.CreateSDiv(x, y); } - case checked_udiv_int: - raise_exception_unless(ctx, - ctx.builder.CreateICmpNE(y, ConstantInt::get(t, 0)), - literal_pointer_val(ctx, jl_diverror_exception)); + case checked_udiv_int: { + auto cond = ctx.builder.CreateICmpNE(y, ConstantInt::get(t, 0)); + setName(ctx.emission_context, cond, "ndivby0"); + raise_exception_unless(ctx, cond, literal_pointer_val(ctx, jl_diverror_exception)); return ctx.builder.CreateUDiv(x, y); - + } case checked_srem_int: return emit_checked_srem_int(ctx, x, y); - case checked_urem_int: - raise_exception_unless(ctx, - ctx.builder.CreateICmpNE(y, ConstantInt::get(t, 0)), - literal_pointer_val(ctx, jl_diverror_exception)); + case checked_urem_int: { + auto cond = ctx.builder.CreateICmpNE(y, ConstantInt::get(t, 0)); + setName(ctx.emission_context, cond, "ndivby0"); + raise_exception_unless(ctx, cond, literal_pointer_val(ctx, jl_diverror_exception)); return ctx.builder.CreateURem(x, y); + } case eq_int: *newtyp = jl_bool_type; return ctx.builder.CreateICmpEQ(x, y); case ne_int: *newtyp = jl_bool_type; return ctx.builder.CreateICmpNE(x, y); diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 1468b4f55f5a7..88e4b0f97927f 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -195,6 +195,8 @@ static jl_callptr_t _jl_compile_codeinst( jl_codegen_params_t params(std::move(context), jl_ExecutionEngine->getDataLayout(), jl_ExecutionEngine->getTargetTriple()); // Locks the context params.cache = true; params.world = world; + params.imaging = imaging_default(); + params.debug_level = jl_options.debug_level; jl_workqueue_t emitted; { orc::ThreadSafeModule result_m = @@ -358,6 +360,8 @@ int jl_compile_extern_c_impl(LLVMOrcThreadSafeModuleRef llvmmod, void *p, void * return std::make_pair(M.getDataLayout(), Triple(M.getTargetTriple())); }); jl_codegen_params_t params(into->getContext(), std::move(target_info.first), std::move(target_info.second)); + params.imaging = imaging_default(); + params.debug_level = jl_options.debug_level; if (pparams == NULL) pparams = ¶ms; assert(pparams->tsctx.getContext() == into->getContext().getContext()); diff --git a/src/jitlayers.h b/src/jitlayers.h index 4e53bbed6e766..3aa3998d3ac23 100644 --- a/src/jitlayers.h +++ b/src/jitlayers.h @@ -237,6 +237,7 @@ typedef struct _jl_codegen_params_t { bool cache = false; bool external_linkage = false; bool imaging; + int debug_level; _jl_codegen_params_t(orc::ThreadSafeContext ctx, DataLayout DL, Triple triple) : tsctx(std::move(ctx)), tsctx_lock(tsctx.getLock()), DL(std::move(DL)), TargetTriple(std::move(triple)), imaging(imaging_default()) {} diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index 13a68be2927de..21567468ffe9e 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -519,29 +519,34 @@ let exename = `$(Base.julia_cmd()) --startup-file=no --color=no` # -g @test readchomp(`$exename -E "Base.JLOptions().debug_level" -g`) == "2" - let code = writereadpipeline("code_llvm(stdout, +, (Int64, Int64), raw=true, dump_module=true)", `$exename -g0`) - @test code[2] - code = code[1] - @test occursin("llvm.module.flags", code) - @test !occursin("llvm.dbg.cu", code) - @test !occursin("int.jl", code) - @test !occursin("Int64", code) - end - let code = writereadpipeline("code_llvm(stdout, +, (Int64, Int64), raw=true, dump_module=true)", `$exename -g1`) - @test code[2] - code = code[1] - @test occursin("llvm.module.flags", code) - @test occursin("llvm.dbg.cu", code) - @test occursin("int.jl", code) - @test !occursin("Int64", code) - end - let code = writereadpipeline("code_llvm(stdout, +, (Int64, Int64), raw=true, dump_module=true)", `$exename -g2`) - @test code[2] - code = code[1] - @test occursin("llvm.module.flags", code) - @test occursin("llvm.dbg.cu", code) - @test occursin("int.jl", code) - @test occursin("\"Int64\"", code) + # --print-before/--print-after with pass names is broken on Windows due to no-gnu-unique issues + if !Sys.iswindows() + withenv("JULIA_LLVM_ARGS" => "--print-before=FinalLowerGC") do + let code = readchomperrors(`$exename -g0 -E "@eval Int64(1)+Int64(1)"`) + @test code[1] + code = code[3] + @test occursin("llvm.module.flags", code) + @test !occursin("llvm.dbg.cu", code) + @test !occursin("int.jl", code) + @test !occursin("\"Int64\"", code) + end + let code = readchomperrors(`$exename -g1 -E "@eval Int64(1)+Int64(1)"`) + @test code[1] + code = code[3] + @test occursin("llvm.module.flags", code) + @test occursin("llvm.dbg.cu", code) + @test occursin("int.jl", code) + @test !occursin("\"Int64\"", code) + end + let code = readchomperrors(`$exename -g2 -E "@eval Int64(1)+Int64(1)"`) + @test code[1] + code = code[3] + @test occursin("llvm.module.flags", code) + @test occursin("llvm.dbg.cu", code) + @test occursin("int.jl", code) + @test occursin("\"Int64\"", code) + end + end end # --check-bounds diff --git a/test/llvmpasses/llvmcall.jl b/test/llvmpasses/llvmcall.jl index a55201c3e3bc3..d39f64d5f839c 100644 --- a/test/llvmpasses/llvmcall.jl +++ b/test/llvmpasses/llvmcall.jl @@ -13,20 +13,109 @@ end @generated foo(x)=:(ccall("extern foo", llvmcall, $x, ($x,), x)) bar(x) = ntuple(i -> VecElement{Float16}(x[i]), 2) -# CHECK: call half @foo(half %{{[0-9]+}}) +# CHECK: define +# CHECK-SAME: half @julia_foo +# CHECK-SAME: { +# CHECK-NOT: define +# CHECK: [[FOO_RET:%.*]] = call half @foo(half [[FOO_ARG:%.*]]) +# CHECK-NOT: define +# CHECK: ret half +# CHECK-NOT: define +# CHECK: } emit(foo, Float16) -# CHECK: call [2 x half] @foo([2 x half] %{{[0-9]+}}) +# COM: Make sure that we don't miss a function by accident (helps localize errors) +# CHECK-NOT: { +# CHECK-NOT: } +# CHECK: define +# CHECK-SAME: nonnull {} addrspace(10)* @jfptr +# CHECK-SAME: { + +# CHECK: define +# CHECK-SAME: [2 x half] @julia_foo +# CHECK-SAME: { +# CHECK-NOT: define +# CHECK: [[FOO_RET:%.*]] = call [2 x half] @foo([2 x half] [[FOO_ARG:%.*]]) +# CHECK-NOT: define +# CHECK: ret [2 x half] +# CHECK-NOT: define +# CHECK: } emit(foo, NTuple{2, Float16}) -# CHECK: call <2 x half> @foo(<2 x half> %{{[0-9]+}}) +# COM: Make sure that we don't miss a function by accident (helps localize errors) +# CHECK-NOT: { +# CHECK-NOT: } +# CHECK: define +# CHECK-SAME: nonnull {} addrspace(10)* @jfptr +# CHECK-SAME: { + +# CHECK: define +# CHECK-SAME: <2 x half> @julia_foo +# CHECK-SAME: { +# CHECK-NOT: define +# CHECK: [[FOO_RET:%.*]] call <2 x half> @foo(<2 x half> [[FOO_ARG:%.*]]) +# CHECK-NOT: define +# CHECK: ret <2 x half> +# CHECK-NOT: define +# CHECK: } emit(foo, NTuple{2, VecElement{Float16}}) -# CHECK: call i8 addrspace(3)* @foo(i8 addrspace(3)* %{{[0-9]+}}) +# COM: Make sure that we don't miss a function by accident (helps localize errors) +# CHECK-NOT: { +# CHECK-NOT: } +# CHECK: define +# CHECK-SAME: nonnull {} addrspace(10)* @jfptr +# CHECK-SAME: { + +# CHECK: define +# CHECK-SAME: i8 addrspace(3)* @julia_foo +# CHECK-SAME: { +# CHECK-NOT: define +# CHECK: [[FOO_RET:%.*]] call i8 addrspace(3)* @foo(i8 addrspace(3)* [[FOO_ARG:%.*]]) +# CHECK-NOT: define +# CHECK: ret i8 addrspace(3)* +# CHECK-NOT: define +# CHECK: } emit(foo, Core.LLVMPtr{Float32, 3}) -# CHECK: call { i32, i32 } @foo({ i32, i32 } %{{[0-9]+}}) +# COM: Make sure that we don't miss a function by accident (helps localize errors) +# CHECK-NOT: { +# CHECK-NOT: } +# CHECK: define +# CHECK-SAME: nonnull {} addrspace(10)* @jfptr +# CHECK-SAME: { + +# CHECK: define +# CHECK-SAME: [2 x i32] @julia_foo +# CHECK-SAME: { +# CHECK-NOT: define +# CHECK: [[FOO_RET:%.*]] call { i32, i32 } @foo({ i32, i32 } [[FOO_ARG:%.*]]) +# CHECK-NOT: define +# CHECK: ret [2 x i32] +# CHECK-NOT: define +# CHECK: } emit(foo, Foo) -# CHECK: define {{(swiftcc )?}}<2 x half> @julia_bar_{{[0-9]+}}( +# COM: Make sure that we don't miss a function by accident (helps localize errors) +# CHECK-NOT: { +# CHECK-NOT: } +# CHECK: define +# CHECK-SAME: nonnull {} addrspace(10)* @jfptr +# CHECK-SAME: { + +# CHECK: define +# CHECK-SAME: <2 x half> @julia_bar +# CHECK-SAME: [2 x half] +# CHECK-SAME: { +# CHECK-NOT: define +# CHECK: ret <2 x half> +# CHECK-NOT: define +# CHECK: } emit(bar, NTuple{2, Float16}) + +# COM: Make sure that we don't miss a function by accident (helps localize errors) +# CHECK-NOT: { +# CHECK-NOT: } +# CHECK: define +# CHECK-SAME: nonnull {} addrspace(10)* @jfptr +# CHECK-SAME: {