Skip to content

Commit a62989b

Browse files
committed
fix some issues with toplevel coverage missing after inlining
1 parent eaa980b commit a62989b

File tree

7 files changed

+37
-37
lines changed

7 files changed

+37
-37
lines changed

base/compiler/inferencestate.jl

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ mutable struct InferenceState
323323
exc_bestguess = Bottom
324324
ipo_effects = EFFECTS_TOTAL
325325

326-
insert_coverage = should_insert_coverage(mod, src)
326+
insert_coverage = should_insert_coverage(mod, src.debuginfo)
327327
if insert_coverage
328328
ipo_effects = Effects(ipo_effects; effect_free = ALWAYS_FALSE)
329329
end
@@ -474,20 +474,21 @@ function compute_trycatch(code::Vector{Any}, ip::BitSet)
474474
end
475475

476476
# check if coverage mode is enabled
477-
function should_insert_coverage(mod::Module, src::CodeInfo)
477+
function should_insert_coverage(mod::Module, debuginfo::DebugInfo)
478478
coverage_enabled(mod) && return true
479479
JLOptions().code_coverage == 3 || return false
480480
# path-specific coverage mode: if any line falls in a tracked file enable coverage for all
481-
return should_insert_coverage(src.debuginfo)
481+
return _should_insert_coverage(debuginfo)
482482
end
483-
should_insert_coverage(mod::Symbol) = is_file_tracked(mod)
484-
should_insert_coverage(mod::Method) = should_insert_coverage(mod.file)
485-
should_insert_coverage(mod::MethodInstance) = should_insert_coverage(mod.def)
486-
should_insert_coverage(mod::Module) = false
487-
function should_insert_coverage(info::DebugInfo)
483+
484+
_should_insert_coverage(mod::Symbol) = is_file_tracked(mod)
485+
_should_insert_coverage(mod::Method) = _should_insert_coverage(mod.file)
486+
_should_insert_coverage(mod::MethodInstance) = _should_insert_coverage(mod.def)
487+
_should_insert_coverage(mod::Module) = false
488+
function _should_insert_coverage(info::DebugInfo)
488489
linetable = info.linetable
489-
linetable === nothing || (should_insert_coverage(linetable) && return true)
490-
should_insert_coverage(info.def) && return true
490+
linetable === nothing || (_should_insert_coverage(linetable) && return true)
491+
_should_insert_coverage(info.def) && return true
491492
return false
492493
end
493494

base/compiler/ssair/inlining.jl

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,6 @@ end
302302

303303
function ir_inline_linetable!(debuginfo::DebugInfoStream, inlinee_debuginfo::DebugInfo, inlinee::MethodInstance)
304304
# Append the linetable of the inlined function to our edges table
305-
extra_coverage_line = false
306305
linetable_offset = 1
307306
while true
308307
if linetable_offset > length(debuginfo.edges)
@@ -313,17 +312,17 @@ function ir_inline_linetable!(debuginfo::DebugInfoStream, inlinee_debuginfo::Deb
313312
end
314313
linetable_offset += 1
315314
end
316-
return Int32(linetable_offset), extra_coverage_line
315+
return Int32(linetable_offset)
317316
end
318317

319318
function ir_prepare_inlining!(insert_node!::Inserter, inline_target::Union{IRCode, IncrementalCompact},
320319
ir::IRCode, di::DebugInfo, mi::MethodInstance, inlined_at::Int32, argexprs::Vector{Any})
321320
def = mi.def::Method
322321
debuginfo = inline_target isa IRCode ? inline_target.debuginfo : inline_target.ir.debuginfo
323322

324-
linetable_offset, extra_coverage_line = ir_inline_linetable!(debuginfo, di, mi)
323+
linetable_offset = ir_inline_linetable!(debuginfo, di, mi)
325324
topline = (inlined_at, linetable_offset, Int32(0))
326-
if extra_coverage_line
325+
if should_insert_coverage(def.module, di)
327326
insert_node!(NewInstruction(Expr(:code_coverage_effect), Nothing, topline))
328327
end
329328
spvals_ssa = nothing

src/codegen.cpp

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8657,6 +8657,7 @@ static jl_llvm_functions_t
86578657
DebugLoc loc;
86588658
StringRef file;
86598659
ssize_t line;
8660+
ssize_t line0; // if this represents pc=1, then also cover the entry to the function (pc=0)
86608661
bool is_user_code;
86618662
int32_t edgeid;
86628663
bool sameframe(const DebugLineTable &other) const {
@@ -8667,12 +8668,12 @@ static jl_llvm_functions_t
86678668
DebugLineTable topinfo;
86688669
topinfo.file = ctx.file;
86698670
topinfo.line = toplineno;
8671+
topinfo.line0 = 0;
86708672
topinfo.is_user_code = mod_is_user_mod;
86718673
topinfo.loc = topdebugloc;
86728674
topinfo.edgeid = 0;
86738675
std::map<std::tuple<StringRef, StringRef>, DISubprogram*> subprograms;
86748676
SmallVector<DebugLineTable, 0> prev_lineinfo, new_lineinfo;
8675-
new_lineinfo.push_back(topinfo);
86768677
auto update_lineinfo = [&] (size_t pc) {
86778678
std::function<bool(jl_debuginfo_t*, jl_value_t*, size_t, size_t)> append_lineinfo =
86788679
[&] (jl_debuginfo_t *debuginfo, jl_value_t *func, size_t to, size_t pc) -> bool {
@@ -8699,6 +8700,13 @@ static jl_llvm_functions_t
86998700
modu = ctx.module;
87008701
info.file = jl_debuginfo_file1(debuginfo);
87018702
info.line = i;
8703+
info.line0 = 0;
8704+
if (pc == 1) {
8705+
struct jl_codeloc_t lineidx = jl_uncompress1_codeloc(debuginfo->codelocs, 0);
8706+
assert(lineidx.to == 0 && lineidx.pc == 0);
8707+
if (lineidx.line > 0 && info.line != lineidx.line)
8708+
info.line0 = lineidx.line;
8709+
}
87028710
if (info.file.empty())
87038711
info.file = "<missing>";
87048712
if (modu == ctx.module)
@@ -8867,8 +8875,11 @@ static jl_llvm_functions_t
88678875
for (; dbg < new_lineinfo.size(); dbg++) {
88688876
const auto &newdbg = new_lineinfo[dbg];
88698877
bool is_tracked = in_tracked_path(newdbg.file);
8870-
if (do_coverage(newdbg.is_user_code, is_tracked))
8878+
if (do_coverage(newdbg.is_user_code, is_tracked)) {
8879+
if (newdbg.line0 != 0 && (dbg >= prev_lineinfo.size() || newdbg.edgeid != prev_lineinfo[dbg].edgeid || newdbg.line0 != prev_lineinfo[dbg].line))
8880+
coverageVisitLine(ctx, newdbg.file, newdbg.line0);
88718881
coverageVisitLine(ctx, newdbg.file, newdbg.line);
8882+
}
88728883
}
88738884
};
88748885
auto mallocVisitStmt = [&] (Value *sync, bool have_dbg_update) {
@@ -8908,18 +8919,8 @@ static jl_llvm_functions_t
89088919
struct jl_codeloc_t lineidx = jl_uncompress1_codeloc(debuginfo->codelocs, pc);
89098920
if (lineidx.line == -1)
89108921
break;
8911-
jl_debuginfo_t *linetable = debuginfo->linetable;
8912-
while (lineidx.line >= 0 && (jl_value_t*)linetable != jl_nothing) {
8913-
if (lineidx.line == 0) {
8914-
lineidx = jl_uncompress1_codeloc(linetable->codelocs, lineidx.line);
8915-
break;
8916-
}
8917-
lineidx = jl_uncompress1_codeloc(linetable->codelocs, lineidx.line);
8918-
linetable = linetable->linetable;
8919-
}
8920-
if (lineidx.line > 0) {
8922+
if (lineidx.line > 0)
89218923
jl_coverage_alloc_line(file, lineidx.line);
8922-
}
89238924
}
89248925
}
89258926
};
@@ -8975,12 +8976,12 @@ static jl_llvm_functions_t
89758976
BB[label] = bb;
89768977
}
89778978

8979+
new_lineinfo.push_back(topinfo);
89788980
Value *sync_bytes = nullptr;
89798981
if (do_malloc_log(true, mod_is_tracked))
89808982
sync_bytes = ctx.builder.CreateCall(prepare_call(diff_gc_total_bytes_func), {});
8981-
// coverage for the function definition line number
8982-
if (do_coverage(topinfo.is_user_code, mod_is_tracked))
8983-
coverageVisitLine(ctx, topinfo.file, topinfo.line);
8983+
// coverage for the function definition line number (topinfo)
8984+
coverageVisitStmt();
89848985

89858986
find_next_stmt(0);
89868987
while (cursor != -1) {

test/cmdlineargs.jl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -560,15 +560,14 @@ let exename = `$(Base.julia_cmd()) --startup-file=no --color=no`
560560
end
561561
do_test()
562562
"""), """
563-
DA:1,1
564563
DA:2,1
565564
DA:3,1
566565
DA:5,1
567566
DA:6,0
568567
DA:9,1
569568
DA:10,1
570-
LH:6
571-
LF:7
569+
LH:5
570+
LF:6
572571
""")
573572
@test contains(coverage_info_for("""
574573
function cov_bug()

test/staged.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,6 @@ let world = Base.get_world_counter()
337337
match = Base._which(Tuple{typeof(sin), Int}; world)
338338
mi = Core.Compiler.specialize_method(match)
339339
lwr = Core.Compiler.retrieve_code_info(mi, world)
340-
#lwr = Core.DebugInfo(mi, lwr.debuginfo, Core.svec(), "") # TODO: @ccall jl_compress_debuginfo(UInt32[(ip, 0, 0)... for ip in 1:length(lwr.code)))::Any
341340
nstmts = length(lwr.code)
342341
di = Core.DebugInfo(Core.Compiler.DebugInfoStream(mi, lwr.debuginfo, nstmts), nstmts)
343342
lwr.debuginfo = di

test/testhelpers/coverage_file.info

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ DA:11,1
1010
DA:12,1
1111
DA:14,0
1212
DA:17,1
13+
DA:18,1
1314
DA:19,1
1415
DA:20,1
1516
DA:22,1
16-
LH:12
17-
LF:14
17+
LH:13
18+
LF:15
1819
end_of_record

test/testhelpers/coverage_file.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ end
2424

2525
success = code_coverage_test() == [1, 2, 3] &&
2626
short_form_func_coverage_test(2) == 4
27-
exit(success ? 0 : 1)
27+
exit(success ? 0 : 1)
2828

2929
# end of file

0 commit comments

Comments
 (0)