Skip to content

Commit 2b0fec6

Browse files
authored
Merge pull request #30251 from JuliaLang/jn/re-coverage
codegen,coverage: handle inlining info
2 parents b482b09 + 4bc155a commit 2b0fec6

File tree

1 file changed

+93
-112
lines changed

1 file changed

+93
-112
lines changed

src/codegen.cpp

Lines changed: 93 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1625,13 +1625,13 @@ static void visitLine(jl_codectx_t &ctx, std::vector<logdata_block*> &vec, int l
16251625
logdata_block &data = *vec[block];
16261626
if (data[line] == 0)
16271627
data[line] = 1;
1628-
Value *v = ConstantExpr::getIntToPtr(
1628+
Value *pv = ConstantExpr::getIntToPtr(
16291629
ConstantInt::get(T_size, (uintptr_t)&data[line]),
16301630
T_pint64);
1631-
ctx.builder.CreateStore(ctx.builder.CreateAdd(ctx.builder.CreateLoad(v, true, name),
1632-
addend),
1633-
v, true); // not atomic, so this might be an underestimate,
1634-
// but it's faster this way
1631+
Value *v = ctx.builder.CreateLoad(pv, true, name);
1632+
v = ctx.builder.CreateAdd(v, addend);
1633+
ctx.builder.CreateStore(v, pv, true); // volatile, not atomic, so this might be an underestimate,
1634+
// but it's faster this way
16351635
}
16361636

16371637
// Code coverage
@@ -1653,10 +1653,8 @@ static logdata_t mallocData;
16531653
static void mallocVisitLine(jl_codectx_t &ctx, StringRef filename, int line)
16541654
{
16551655
assert(!imaging_mode);
1656-
if (filename == "" || filename == "none" || filename == "no file" || filename == "<missing>" || line < 0) {
1657-
jl_gc_sync_total_bytes();
1656+
if (filename == "" || filename == "none" || filename == "no file" || filename == "<missing>" || line < 0)
16581657
return;
1659-
}
16601658
Value *addend = ctx.builder.CreateCall(prepare_call(diff_gc_total_bytes_func), {});
16611659
visitLine(ctx, mallocData[filename], line, addend, "bytecnt");
16621660
}
@@ -5288,31 +5286,30 @@ static std::unique_ptr<Module> emit_function(
52885286
// step 1b. unpack debug information
52895287
int coverage_mode = jl_options.code_coverage;
52905288
int malloc_log_mode = jl_options.malloc_log;
5291-
StringRef filename = "<missing>";
5289+
if (!JL_FEAT_TEST(ctx, code_coverage))
5290+
coverage_mode = JL_LOG_NONE;
5291+
if (!JL_FEAT_TEST(ctx, track_allocations))
5292+
malloc_log_mode = JL_LOG_NONE;
5293+
5294+
ctx.file = "<missing>";
52925295
StringRef dbgFuncName = ctx.name;
52935296
int toplineno = -1;
52945297
if (jl_is_method(lam->def.method)) {
52955298
toplineno = lam->def.method->line;
52965299
if (lam->def.method->file != empty_sym)
5297-
filename = jl_symbol_name(lam->def.method->file);
5300+
ctx.file = jl_symbol_name(lam->def.method->file);
52985301
}
52995302
else if (jl_array_len(src->linetable) > 0) {
53005303
jl_value_t *locinfo = jl_array_ptr_ref(src->linetable, 0);
5301-
filename = jl_symbol_name((jl_sym_t*)jl_fieldref_noalloc(locinfo, 2));
5304+
ctx.file = jl_symbol_name((jl_sym_t*)jl_fieldref_noalloc(locinfo, 2));
53025305
toplineno = jl_unbox_long(jl_fieldref(locinfo, 3));
53035306
}
5304-
ctx.file = filename;
53055307
// jl_printf(JL_STDERR, "\n*** compiling %s at %s:%d\n\n",
5306-
// jl_symbol_name(ctx.name), filename.str().c_str(), toplineno);
5308+
// jl_symbol_name(ctx.name), ctx.file.str().c_str(), toplineno);
53075309

53085310
ctx.debug_enabled = true;
5309-
if (dbgFuncName.empty()) {
5310-
// special value: if function name is empty, disable debug info
5311-
coverage_mode = JL_LOG_NONE;
5312-
malloc_log_mode = JL_LOG_NONE;
5313-
//dbgFuncName = filename; // for testing, uncomment this line
5314-
ctx.debug_enabled = !dbgFuncName.empty();
5315-
}
5311+
if (dbgFuncName.empty()) // Should never happen anymore?
5312+
ctx.debug_enabled = 0;
53165313
if (jl_options.debug_level == 0)
53175314
ctx.debug_enabled = 0;
53185315

@@ -5481,7 +5478,7 @@ static std::unique_ptr<Module> emit_function(
54815478
DebugLoc noDbg, topdebugloc;
54825479
if (ctx.debug_enabled) {
54835480
// TODO: Fix when moving to new LLVM version
5484-
topfile = dbuilder.createFile(filename, ".");
5481+
topfile = dbuilder.createFile(ctx.file, ".");
54855482
DICompileUnit *CU = dbuilder.createCompileUnit(0x01, topfile, "julia", true, "", 0);
54865483
DISubroutineType *subrty;
54875484
if (jl_options.debug_level <= 1) {
@@ -5862,92 +5859,57 @@ static std::unique_ptr<Module> emit_function(
58625859
!jl_is_submodule(mod, jl_core_module));
58635860
};
58645861
bool mod_is_user_mod = in_user_mod(ctx.module);
5865-
struct StmtProp {
5862+
struct DebugLineTable {
58665863
DebugLoc loc;
58675864
StringRef file;
58685865
ssize_t line;
5869-
bool loc_changed;
5870-
bool is_poploc;
5871-
bool in_user_code;
5866+
bool is_user_code;
5867+
unsigned inlined_at;
58725868
};
5873-
std::vector<StmtProp> stmtprops(stmtslen);
5874-
{ // if new style IR
5875-
std::vector<DebugLoc> linetable;
5869+
std::vector<DebugLineTable> linetable;
5870+
{
58765871
size_t nlocs = jl_array_len(src->linetable);
5877-
if (ctx.debug_enabled) {
5878-
std::map<std::tuple<StringRef, StringRef>, DISubprogram*> subprograms;
5879-
linetable.resize(nlocs + 1);
5880-
linetable[0] = noDbg;
5881-
for (size_t i = 0; i < nlocs; i++) {
5882-
// LineInfoNode(mod::Module, method::Symbol, file::Symbol, line::Int, inlined_at::Int)
5883-
jl_value_t *locinfo = jl_array_ptr_ref(src->linetable, i);
5884-
int inlined_at, line;
5885-
jl_sym_t *file;
5886-
StringRef filename = ctx.file;
5887-
StringRef fname;
5888-
assert(jl_typeis(locinfo, jl_lineinfonode_type));
5889-
{
5890-
jl_sym_t *method = (jl_sym_t*)jl_fieldref_noalloc(locinfo, 1);
5891-
file = (jl_sym_t*)jl_fieldref_noalloc(locinfo, 2);
5892-
line = jl_unbox_long(jl_fieldref(locinfo, 3));
5893-
inlined_at = jl_unbox_long(jl_fieldref(locinfo, 4));
5894-
assert((size_t)inlined_at <= i);
5895-
filename = jl_symbol_name(file);
5896-
if (filename.empty())
5897-
filename = "<missing>";
5898-
fname = jl_symbol_name(method);
5899-
if (fname.empty())
5900-
fname = "macro expansion";
5901-
}
5902-
if (inlined_at == 0 && filename == ctx.file) { // if everything matches, emit a toplevel line number
5903-
linetable[i + 1] = DebugLoc::get(line, 0, SP, NULL);
5872+
std::map<std::tuple<StringRef, StringRef>, DISubprogram*> subprograms;
5873+
linetable.resize(nlocs + 1);
5874+
for (size_t i = 0; i < nlocs; i++) {
5875+
// LineInfoNode(mod::Module, method::Symbol, file::Symbol, line::Int, inlined_at::Int)
5876+
jl_value_t *locinfo = jl_array_ptr_ref(src->linetable, i);
5877+
DebugLineTable &info = linetable[i + 1];
5878+
assert(jl_typeis(locinfo, jl_lineinfonode_type));
5879+
jl_module_t *module = (jl_module_t*)jl_fieldref_noalloc(locinfo, 0);
5880+
if (module == ctx.module)
5881+
info.is_user_code = mod_is_user_mod;
5882+
else
5883+
info.is_user_code = in_user_mod(module);
5884+
jl_sym_t *method = (jl_sym_t*)jl_fieldref_noalloc(locinfo, 1);
5885+
jl_sym_t *filesym = (jl_sym_t*)jl_fieldref_noalloc(locinfo, 2);
5886+
info.line = jl_unbox_long(jl_fieldref(locinfo, 3));
5887+
info.inlined_at = jl_unbox_long(jl_fieldref(locinfo, 4));
5888+
assert(info.inlined_at <= i);
5889+
info.file = jl_symbol_name(filesym);
5890+
if (info.file.empty())
5891+
info.file = "<missing>";
5892+
if (ctx.debug_enabled) {
5893+
StringRef fname = jl_symbol_name(method);
5894+
if (fname.empty())
5895+
fname = "macro expansion";
5896+
if (info.inlined_at == 0 && info.file == ctx.file) { // if everything matches, emit a toplevel line number
5897+
info.loc = DebugLoc::get(info.line, 0, SP, NULL);
59045898
}
59055899
else { // otherwise, describe this as an inlining frame
5906-
DISubprogram *&inl_SP = subprograms[std::make_tuple(fname, filename)];
5900+
DISubprogram *&inl_SP = subprograms[std::make_tuple(fname, info.file)];
59075901
if (inl_SP == NULL) {
5908-
DIFile *difile = dbuilder.createFile(filename, ".");
5902+
DIFile *difile = dbuilder.createFile(info.file, ".");
59095903
inl_SP = dbuilder.createFunction(
59105904
difile, std::string(fname) + ";",
59115905
fname, difile, 0, jl_di_func_null_sig,
59125906
false, true, 0, DIFlagZero, true, nullptr);
59135907
}
5914-
DebugLoc inl_loc = (inlined_at == 0) ? DebugLoc::get(0, 0, SP, NULL) : linetable.at(inlined_at);
5915-
linetable[i + 1] = DebugLoc::get(line, 0, inl_SP, inl_loc);
5908+
DebugLoc inl_loc = (info.inlined_at == 0) ? DebugLoc::get(0, 0, SP, NULL) : linetable.at(info.inlined_at).loc;
5909+
info.loc = DebugLoc::get(info.line, 0, inl_SP, inl_loc);
59165910
}
59175911
}
59185912
}
5919-
size_t prev_loc = 0;
5920-
for (i = 0; i < stmtslen; i++) {
5921-
size_t loc = ((int32_t*)jl_array_data(src->codelocs))[i];
5922-
StmtProp &cur_prop = stmtprops[i];
5923-
cur_prop.is_poploc = false;
5924-
if (loc > 0) {
5925-
jl_value_t *locinfo = jl_array_ptr_ref(src->linetable, loc - 1);
5926-
if (ctx.debug_enabled)
5927-
cur_prop.loc = linetable.at(loc);
5928-
else
5929-
cur_prop.loc = noDbg;
5930-
assert(jl_typeis(locinfo, jl_lineinfonode_type));
5931-
{
5932-
jl_module_t *module = (jl_module_t*)jl_fieldref_noalloc(locinfo, 0);
5933-
cur_prop.file = jl_symbol_name((jl_sym_t*)jl_fieldref_noalloc(locinfo, 2));
5934-
cur_prop.line = jl_unbox_long(jl_fieldref(locinfo, 3));
5935-
if (module == ctx.module)
5936-
cur_prop.in_user_code = mod_is_user_mod;
5937-
else
5938-
cur_prop.in_user_code = in_user_mod(module);
5939-
}
5940-
cur_prop.loc_changed = (loc != prev_loc); // for code-coverage
5941-
prev_loc = loc;
5942-
}
5943-
else {
5944-
cur_prop.loc = noDbg;
5945-
cur_prop.file = "";
5946-
cur_prop.line = -1;
5947-
cur_prop.loc_changed = false;
5948-
cur_prop.in_user_code = false;
5949-
}
5950-
}
59515913
}
59525914
Instruction &prologue_end = ctx.builder.GetInsertBlock()->back();
59535915

@@ -5957,9 +5919,6 @@ static std::unique_ptr<Module> emit_function(
59575919
std::map<int, BasicBlock*> BB;
59585920
std::map<size_t, BasicBlock*> come_from_bb;
59595921
int cursor = 0;
5960-
// Whether we are doing codegen in statement order.
5961-
// We need to update debug location if this is false even if
5962-
// `loc_changed` is false.
59635922
auto find_next_stmt = [&] (int seq_next) {
59645923
// new style ir is always in dominance order, but frontend IR might not be
59655924
// `seq_next` is the next statement we want to emit
@@ -5995,15 +5954,40 @@ static std::unique_ptr<Module> emit_function(
59955954
};
59965955

59975956
auto do_coverage = [&] (bool in_user_code) {
5998-
if (!JL_FEAT_TEST(ctx, code_coverage)) return false;
59995957
return (coverage_mode == JL_LOG_ALL ||
60005958
(coverage_mode == JL_LOG_USER && in_user_code));
60015959
};
60025960
auto do_malloc_log = [&] (bool in_user_code) {
6003-
if (!JL_FEAT_TEST(ctx, track_allocations)) return false;
60045961
return (malloc_log_mode == JL_LOG_ALL ||
60055962
(malloc_log_mode == JL_LOG_USER && in_user_code));
60065963
};
5964+
std::vector<unsigned> current_lineinfo, new_lineinfo;
5965+
auto coverageVisitStmt = [&] (size_t dbg) {
5966+
if (dbg == 0)
5967+
return;
5968+
while (dbg) {
5969+
new_lineinfo.push_back(dbg);
5970+
dbg = linetable[dbg].inlined_at;
5971+
}
5972+
current_lineinfo.resize(new_lineinfo.size(), 0);
5973+
for (dbg = 0; dbg < new_lineinfo.size(); dbg++) {
5974+
unsigned newdbg = new_lineinfo[new_lineinfo.size() - dbg - 1];
5975+
if (newdbg != current_lineinfo[dbg]) {
5976+
current_lineinfo[dbg] = newdbg;
5977+
const auto &info = linetable[newdbg];
5978+
if (do_coverage(info.is_user_code))
5979+
coverageVisitLine(ctx, info.file, info.line);
5980+
}
5981+
}
5982+
new_lineinfo.clear();
5983+
};
5984+
auto mallocVisitStmt = [&] (unsigned dbg) {
5985+
if (!do_malloc_log(mod_is_user_mod) || dbg == 0)
5986+
return;
5987+
while (linetable[dbg].inlined_at)
5988+
dbg = linetable[dbg].inlined_at;
5989+
mallocVisitLine(ctx, ctx.file, linetable[dbg].line);
5990+
};
60075991

60085992
come_from_bb[0] = ctx.builder.GetInsertBlock();
60095993

@@ -6058,19 +6042,20 @@ static std::unique_ptr<Module> emit_function(
60586042
BB[label] = bb;
60596043
}
60606044

6061-
if (coverage_mode != JL_LOG_NONE && do_coverage(in_user_mod(ctx.module)))
6062-
coverageVisitLine(ctx, filename, toplineno);
6045+
if (do_coverage(mod_is_user_mod))
6046+
coverageVisitLine(ctx, ctx.file, toplineno);
6047+
if (do_malloc_log(mod_is_user_mod))
6048+
mallocVisitLine(ctx, ctx.file, toplineno);
60636049
find_next_stmt(0);
60646050
while (cursor != -1) {
6065-
auto &props = stmtprops[cursor];
6066-
if (ctx.debug_enabled)
6067-
ctx.builder.SetCurrentDebugLocation(props.loc);
6051+
int32_t debuginfoloc = ((int32_t*)jl_array_data(src->codelocs))[cursor];
6052+
if (debuginfoloc > 0) {
6053+
if (ctx.debug_enabled)
6054+
ctx.builder.SetCurrentDebugLocation(linetable[debuginfoloc].loc);
6055+
coverageVisitStmt(debuginfoloc);
6056+
}
60686057
jl_value_t *stmt = jl_array_ptr_ref(stmts, cursor);
60696058
jl_expr_t *expr = jl_is_expr(stmt) ? (jl_expr_t*)stmt : nullptr;
6070-
// Legacy IR: disables coverage for pop_loc since it doesn't start a new expression
6071-
if (props.loc_changed && do_coverage(props.in_user_code) && !props.is_poploc) {
6072-
coverageVisitLine(ctx, props.file, props.line);
6073-
}
60746059
if (expr && expr->head == unreachable_sym) {
60756060
ctx.builder.CreateUnreachable();
60766061
find_next_stmt(-1);
@@ -6162,8 +6147,7 @@ static std::unique_ptr<Module> emit_function(
61626147
}
61636148
}
61646149

6165-
if (do_malloc_log(props.in_user_code) && props.line != -1)
6166-
mallocVisitLine(ctx, props.file, props.line);
6150+
mallocVisitStmt(debuginfoloc);
61676151
if (toplevel)
61686152
ctx.builder.CreateStore(last_age, ctx.world_age_field);
61696153
assert(type_is_ghost(retty) || returninfo.cc == jl_returninfo_t::SRet ||
@@ -6205,8 +6189,7 @@ static std::unique_ptr<Module> emit_function(
62056189
jl_value_t *cond = args[0];
62066190
int lname = jl_unbox_long(args[1]);
62076191
Value *isfalse = emit_condition(ctx, cond, "if");
6208-
if (do_malloc_log(props.in_user_code) && props.line != -1)
6209-
mallocVisitLine(ctx, props.file, props.line);
6192+
mallocVisitStmt(debuginfoloc);
62106193
come_from_bb[cursor+1] = ctx.builder.GetInsertBlock();
62116194
workstack.push_back(lname - 1);
62126195
BasicBlock *ifnot = BB[lname];
@@ -6244,9 +6227,7 @@ static std::unique_ptr<Module> emit_function(
62446227
}
62456228
else {
62466229
emit_stmtpos(ctx, stmt, cursor);
6247-
if (do_malloc_log(props.in_user_code) && props.line != -1) {
6248-
mallocVisitLine(ctx, props.file, props.line);
6249-
}
6230+
mallocVisitStmt(debuginfoloc);
62506231
}
62516232
find_next_stmt(cursor + 1);
62526233
}

0 commit comments

Comments
 (0)