From 5db280db2e5f9fa23457e86324e56eac130cca1d Mon Sep 17 00:00:00 2001 From: pchintalapudi <34727397+pchintalapudi@users.noreply.github.com> Date: Fri, 4 Mar 2022 13:36:24 -0500 Subject: [PATCH] Create debuginfo once per module (#43770) --- src/cgutils.cpp | 56 +++++++++++++++++++++++++---- src/codegen.cpp | 95 ++++++++++++++++--------------------------------- 2 files changed, 79 insertions(+), 72 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 57d130d202325..39af20a47a7df 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -109,11 +109,11 @@ Metadata *to_md_tree(jl_value_t *val, LLVMContext &ctxt) { // --- Debug info --- -static DIType *_julia_type_to_di(jl_codegen_params_t *ctx, jl_value_t *jt, DIBuilder *dbuilder, bool isboxed) +static DIType *_julia_type_to_di(jl_codegen_params_t *ctx, jl_debugcache_t &debuginfo, jl_value_t *jt, DIBuilder *dbuilder, bool isboxed) { jl_datatype_t *jdt = (jl_datatype_t*)jt; if (isboxed || !jl_is_datatype(jt) || !jdt->isconcretetype) - return jl_pvalue_dillvmt; + return debuginfo.jl_pvalue_dillvmt; assert(jdt->layout); DIType* _ditype = NULL; DIType* &ditype = (ctx ? ctx->ditypes[jdt] : _ditype); @@ -131,10 +131,10 @@ static DIType *_julia_type_to_di(jl_codegen_params_t *ctx, jl_value_t *jt, DIBui jl_value_t *el = jl_field_type_concrete(jdt, i); DIType *di; if (jl_field_isptr(jdt, i)) - di = jl_pvalue_dillvmt; + di = debuginfo.jl_pvalue_dillvmt; // TODO: elseif jl_islayout_inline else - di = _julia_type_to_di(ctx, el, dbuilder, false); + di = _julia_type_to_di(ctx, debuginfo, el, dbuilder, false); Elements[i] = di; } DINodeArray ElemArray = dbuilder->getOrCreateArray(Elements); @@ -157,14 +157,56 @@ static DIType *_julia_type_to_di(jl_codegen_params_t *ctx, jl_value_t *jt, DIBui } else { // return a typealias for types with hidden content - ditype = dbuilder->createTypedef(jl_pvalue_dillvmt, tname, NULL, 0, NULL); + ditype = dbuilder->createTypedef(debuginfo.jl_pvalue_dillvmt, tname, NULL, 0, NULL); } return ditype; } -static DIType *julia_type_to_di(jl_codectx_t &ctx, jl_value_t *jt, DIBuilder *dbuilder, bool isboxed) +static DIType *julia_type_to_di(jl_codectx_t &ctx, jl_debugcache_t &debuginfo, jl_value_t *jt, DIBuilder *dbuilder, bool isboxed) { - return _julia_type_to_di(&ctx.emission_context, jt, dbuilder, isboxed); + return _julia_type_to_di(&ctx.emission_context, debuginfo, jt, dbuilder, isboxed); +} + +void jl_debugcache_t::initialize(Module *m) { + if (initialized) { + return; + } + initialized = true; + // add needed base debugging definitions to our LLVM environment + DIBuilder dbuilder(*m); + DIFile *julia_h = dbuilder.createFile("julia.h", ""); + DICompositeType *jl_value_dillvmt = dbuilder.createStructType(nullptr, + "jl_value_t", + julia_h, + 71, // At the time of this writing. Not sure if it's worth it to keep this in sync + 0 * 8, // sizeof(jl_value_t) * 8, + __alignof__(void*) * 8, // __alignof__(jl_value_t) * 8, + DINode::FlagZero, // Flags + nullptr, // Derived from + nullptr); // Elements - will be corrected later + + jl_pvalue_dillvmt = dbuilder.createPointerType(jl_value_dillvmt, sizeof(jl_value_t*) * 8, + __alignof__(jl_value_t*) * 8); + + SmallVector Elts; + std::vector diargs(0); + Elts.push_back(jl_pvalue_dillvmt); + dbuilder.replaceArrays(jl_value_dillvmt, + dbuilder.getOrCreateArray(Elts)); + + jl_ppvalue_dillvmt = dbuilder.createPointerType(jl_pvalue_dillvmt, sizeof(jl_value_t**) * 8, + __alignof__(jl_value_t**) * 8); + + diargs.push_back(jl_pvalue_dillvmt); // Return Type (ret value) + diargs.push_back(jl_pvalue_dillvmt); // First Argument (function) + diargs.push_back(jl_ppvalue_dillvmt); // Second Argument (argv) + // Third argument (length(argv)) + diargs.push_back(_julia_type_to_di(NULL, *this, (jl_value_t*)jl_int32_type, &dbuilder, false)); + + jl_di_func_sig = dbuilder.createSubroutineType( + dbuilder.getOrCreateTypeArray(diargs)); + jl_di_func_null_sig = dbuilder.createSubroutineType( + dbuilder.getOrCreateTypeArray(None)); } static Value *emit_pointer_from_objref(jl_codectx_t &ctx, Value *V) diff --git a/src/codegen.cpp b/src/codegen.cpp index 80fc52471bb45..71de86ad1373a 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -343,12 +343,20 @@ struct jl_tbaacache_t { } }; -// Basic DITypes -static DICompositeType *jl_value_dillvmt; -static DIDerivedType *jl_pvalue_dillvmt; -static DIDerivedType *jl_ppvalue_dillvmt; -static DISubroutineType *jl_di_func_sig; -static DISubroutineType *jl_di_func_null_sig; +struct jl_debugcache_t { + // Basic DITypes + DIDerivedType *jl_pvalue_dillvmt; + DIDerivedType *jl_ppvalue_dillvmt; + DISubroutineType *jl_di_func_sig; + DISubroutineType *jl_di_func_null_sig; + bool initialized; + + jl_debugcache_t() + : jl_pvalue_dillvmt(nullptr), jl_ppvalue_dillvmt(nullptr), + jl_di_func_sig(nullptr), jl_di_func_null_sig(nullptr), initialized(false) {} + + void initialize(Module *m); +}; // constants @@ -6252,14 +6260,14 @@ static void emit_sret_roots(jl_codectx_t &ctx, bool isptr, Value *Src, Type *T, } static DISubroutineType * -get_specsig_di(jl_codectx_t &ctx, jl_value_t *rt, jl_value_t *sig, DIBuilder &dbuilder) +get_specsig_di(jl_codectx_t &ctx, jl_debugcache_t &debuginfo, jl_value_t *rt, jl_value_t *sig, DIBuilder &dbuilder) { size_t nargs = jl_nparams(sig); // TODO: if this is a Varargs function, our debug info for the `...` var may be misleading std::vector ditypes(nargs + 1); - ditypes[0] = julia_type_to_di(ctx, rt, &dbuilder, false); + ditypes[0] = julia_type_to_di(ctx, debuginfo, rt, &dbuilder, false); for (size_t i = 0; i < nargs; i++) { jl_value_t *jt = jl_tparam(sig, i); - ditypes[i + 1] = julia_type_to_di(ctx, jt, &dbuilder, false); + ditypes[i + 1] = julia_type_to_di(ctx, debuginfo, jt, &dbuilder, false); } return dbuilder.createSubroutineType(dbuilder.getOrCreateTypeArray(ditypes)); } @@ -6439,6 +6447,8 @@ static std::pair, jl_llvm_functions_t> // allocate Function declarations and wrapper objects Module *M = _jl_create_llvm_module(ctx.name, ctx.builder.getContext(), ctx.params, jl_ExecutionEngine->getDataLayout(), jl_ExecutionEngine->getTargetTriple()); + jl_debugcache_t debuginfo; + debuginfo.initialize(M); jl_returninfo_t returninfo = {}; Function *f = NULL; bool has_sret = false; @@ -6561,13 +6571,13 @@ static std::pair, jl_llvm_functions_t> DISubroutineType *subrty; if (jl_options.debug_level <= 1) { - subrty = jl_di_func_null_sig; + subrty = debuginfo.jl_di_func_null_sig; } else if (!specsig) { - subrty = jl_di_func_sig; + subrty = debuginfo.jl_di_func_sig; } else { - subrty = get_specsig_di(ctx, jlrettype, lam->specTypes, dbuilder); + subrty = get_specsig_di(ctx, debuginfo, jlrettype, lam->specTypes, dbuilder); } SP = dbuilder.createFunction(CU ,dbgFuncName // Name @@ -6599,7 +6609,7 @@ static std::pair, jl_llvm_functions_t> topfile, // File toplineno == -1 ? 0 : toplineno, // Line // Variable type - julia_type_to_di(ctx, varinfo.value.typ, &dbuilder, false), + julia_type_to_di(ctx, debuginfo, varinfo.value.typ, &dbuilder, false), AlwaysPreserve, // May be deleted if optimized out DINode::FlagZero); // Flags (TODO: Do we need any) } @@ -6610,7 +6620,7 @@ static std::pair, jl_llvm_functions_t> has_sret + nreq + 1, // Argument number (1-based) topfile, // File toplineno == -1 ? 0 : toplineno, // Line (for now, use lineno of the function) - julia_type_to_di(ctx, ctx.slots[ctx.vaSlot].value.typ, &dbuilder, false), + julia_type_to_di(ctx, debuginfo, ctx.slots[ctx.vaSlot].value.typ, &dbuilder, false), AlwaysPreserve, // May be deleted if optimized out DINode::FlagZero); // Flags (TODO: Do we need any) } @@ -6625,7 +6635,7 @@ static std::pair, jl_llvm_functions_t> jl_symbol_name(s), // Variable name topfile, // File toplineno == -1 ? 0 : toplineno, // Line (for now, use lineno of the function) - julia_type_to_di(ctx, varinfo.value.typ, &dbuilder, false), // Variable type + julia_type_to_di(ctx, debuginfo, varinfo.value.typ, &dbuilder, false), // Variable type AlwaysPreserve, // May be deleted if optimized out DINode::FlagZero // Flags (TODO: Do we need any) ); @@ -6714,7 +6724,7 @@ static std::pair, jl_llvm_functions_t> varinfo.value = mark_julia_slot(lv, jt, NULL, ctx.tbaa(), ctx.tbaa().tbaa_stack); alloc_def_flag(ctx, varinfo); if (ctx.debug_enabled && varinfo.dinfo) { - assert((Metadata*)varinfo.dinfo->getType() != jl_pvalue_dillvmt); + assert((Metadata*)varinfo.dinfo->getType() != debuginfo.jl_pvalue_dillvmt); dbuilder.insertDeclare(lv, varinfo.dinfo, dbuilder.createExpression(), topdebugloc, ctx.builder.GetInsertBlock()); @@ -6732,7 +6742,7 @@ static std::pair, jl_llvm_functions_t> varinfo.boxroot = av; if (ctx.debug_enabled && varinfo.dinfo) { DIExpression *expr; - if ((Metadata*)varinfo.dinfo->getType() == jl_pvalue_dillvmt) { + if ((Metadata*)varinfo.dinfo->getType() == debuginfo.jl_pvalue_dillvmt) { expr = dbuilder.createExpression(); } else { @@ -6855,7 +6865,7 @@ static std::pair, jl_llvm_functions_t> addr.push_back(llvm::dwarf::DW_OP_deref); addr.push_back(llvm::dwarf::DW_OP_plus_uconst); addr.push_back((i - 1) * sizeof(void*)); - if ((Metadata*)vi.dinfo->getType() != jl_pvalue_dillvmt) + if ((Metadata*)vi.dinfo->getType() != debuginfo.jl_pvalue_dillvmt) addr.push_back(llvm::dwarf::DW_OP_deref); dbuilder.insertDeclare(pargArray, vi.dinfo, dbuilder.createExpression(addr), topdebugloc, @@ -6896,7 +6906,7 @@ static std::pair, jl_llvm_functions_t> Value *parg; if (theArg.ispointer()) { parg = theArg.V; - if ((Metadata*)vi.dinfo->getType() != jl_pvalue_dillvmt) + if ((Metadata*)vi.dinfo->getType() != debuginfo.jl_pvalue_dillvmt) addr.push_back(llvm::dwarf::DW_OP_deref); } else { @@ -7034,7 +7044,7 @@ static std::pair, jl_llvm_functions_t> ,fname // LinkageName ,difile // File ,0 // LineNo - ,jl_di_func_null_sig // Ty + ,debuginfo.jl_di_func_null_sig // Ty ,0 // ScopeLine ,DINode::FlagZero // Flags ,DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized // SPFlags @@ -8000,48 +8010,6 @@ static JuliaVariable *julia_const_gv(jl_value_t *val) return nullptr; } -static void init_julia_llvm_env(Module *m) -{ - // every variable or function mapped in this function must be - // exported from libjulia, to support static compilation - - // add needed base debugging definitions to our LLVM environment - DIBuilder dbuilder(*m); - DIFile *julia_h = dbuilder.createFile("julia.h", ""); - jl_value_dillvmt = dbuilder.createStructType(nullptr, - "jl_value_t", - julia_h, - 71, // At the time of this writing. Not sure if it's worth it to keep this in sync - 0 * 8, // sizeof(jl_value_t) * 8, - __alignof__(void*) * 8, // __alignof__(jl_value_t) * 8, - DINode::FlagZero, // Flags - nullptr, // Derived from - nullptr); // Elements - will be corrected later - - jl_pvalue_dillvmt = dbuilder.createPointerType(jl_value_dillvmt, sizeof(jl_value_t*) * 8, - __alignof__(jl_value_t*) * 8); - - SmallVector Elts; - std::vector diargs(0); - Elts.push_back(jl_pvalue_dillvmt); - dbuilder.replaceArrays(jl_value_dillvmt, - dbuilder.getOrCreateArray(Elts)); - - jl_ppvalue_dillvmt = dbuilder.createPointerType(jl_pvalue_dillvmt, sizeof(jl_value_t**) * 8, - __alignof__(jl_value_t**) * 8); - - diargs.push_back(jl_pvalue_dillvmt); // Return Type (ret value) - diargs.push_back(jl_pvalue_dillvmt); // First Argument (function) - diargs.push_back(jl_ppvalue_dillvmt); // Second Argument (argv) - // Third argument (length(argv)) - diargs.push_back(_julia_type_to_di(NULL, (jl_value_t*)jl_int32_type, &dbuilder, false)); - - jl_di_func_sig = dbuilder.createSubroutineType( - dbuilder.getOrCreateTypeArray(diargs)); - jl_di_func_null_sig = dbuilder.createSubroutineType( - dbuilder.getOrCreateTypeArray(None)); -} - static void init_jit_functions(void) { add_named_global(jlstack_chk_guard_var, &__stack_chk_guard); @@ -8303,9 +8271,6 @@ extern "C" JL_DLLEXPORT void jl_init_codegen_impl(void) jl_init_jit(); init_jit_functions(); - Module *m = _jl_create_llvm_module("julia", *jl_ExecutionEngine->getContext().getContext(), &jl_default_cgparams, jl_ExecutionEngine->getDataLayout(), jl_ExecutionEngine->getTargetTriple()); - init_julia_llvm_env(m); - jl_init_intrinsic_functions_codegen(); }