Skip to content

Commit 065e10c

Browse files
committed
link: new incremental line number update API
1 parent 136c5a9 commit 065e10c

File tree

14 files changed

+90
-71
lines changed

14 files changed

+90
-71
lines changed

change_line_number

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#target=x86_64-linux-selfhosted
2+
#update=initial version
3+
#file=main.zig
4+
const std = @import("std");
5+
pub fn main() !void {
6+
try std.io.getStdOut().writeAll("foo\n");
7+
}
8+
#expect_stdout="foo\n"
9+
#update=change line number
10+
#file=main.zig
11+
const std = @import("std");
12+
13+
pub fn main() !void {
14+
try std.io.getStdOut().writeAll("foo\n");
15+
}
16+
#expect_stdout="foo\n"

src/Compilation.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,7 @@ const Job = union(enum) {
348348
/// Corresponds to the task in `link.Task`.
349349
/// Only needed for backends that haven't yet been updated to not race against Sema.
350350
codegen_type: InternPool.Index,
351+
update_line_number: InternPool.TrackedInst.Index,
351352
/// The `AnalUnit`, which is *not* a `func`, must be semantically analyzed.
352353
/// This may be its first time being analyzed, or it may be outdated.
353354
/// If the unit is a function, a `codegen_func` job will then be queued.
@@ -3718,6 +3719,9 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre
37183719
.codegen_type => |ty| {
37193720
comp.dispatchCodegenTask(tid, .{ .codegen_type = ty });
37203721
},
3722+
.update_line_number => |ti| {
3723+
comp.dispatchCodegenTask(tid, .{ .update_line_number = ti });
3724+
},
37213725
.analyze_func => |func| {
37223726
const named_frame = tracy.namedFrame("analyze_func");
37233727
defer named_frame.end();

src/Zcu/PerThread.zig

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@ fn cleanupUpdatedFiles(gpa: Allocator, updated_files: *std.AutoArrayHashMapUnman
379379
pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {
380380
assert(pt.tid == .main);
381381
const zcu = pt.zcu;
382+
const comp = zcu.comp;
382383
const ip = &zcu.intern_pool;
383384
const gpa = zcu.gpa;
384385

@@ -435,8 +436,19 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {
435436

436437
const old_zir = file.prev_zir.?.*;
437438
const new_zir = file.zir;
438-
const old_tag = old_zir.instructions.items(.tag);
439-
const old_data = old_zir.instructions.items(.data);
439+
const old_tag = old_zir.instructions.items(.tag)[@intFromEnum(old_inst)];
440+
const old_data = old_zir.instructions.items(.data)[@intFromEnum(old_inst)];
441+
442+
switch (old_tag) {
443+
.declaration => {
444+
const old_line = old_zir.getDeclaration(old_inst).src_line;
445+
const new_line = new_zir.getDeclaration(new_inst).src_line;
446+
if (old_line != new_line) {
447+
try comp.queueJob(.{ .update_line_number = tracked_inst_index });
448+
}
449+
},
450+
else => {},
451+
}
440452

441453
if (old_zir.getAssociatedSrcHash(old_inst)) |old_hash| hash_changed: {
442454
if (new_zir.getAssociatedSrcHash(new_inst)) |new_hash| {
@@ -455,8 +467,8 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {
455467
}
456468

457469
// If this is a `struct_decl` etc, we must invalidate any outdated namespace dependencies.
458-
const has_namespace = switch (old_tag[@intFromEnum(old_inst)]) {
459-
.extended => switch (old_data[@intFromEnum(old_inst)].extended.opcode) {
470+
const has_namespace = switch (old_tag) {
471+
.extended => switch (old_data.extended.opcode) {
460472
.struct_decl, .union_decl, .opaque_decl, .enum_decl => true,
461473
else => false,
462474
},
@@ -2517,8 +2529,6 @@ const ScanDeclIter = struct {
25172529
);
25182530
try comp.queueJob(.{ .analyze_comptime_unit = unit });
25192531
}
2520-
2521-
// TODO: we used to do line number updates here, but this is an inappropriate place for this logic to live.
25222532
}
25232533
};
25242534

@@ -3152,6 +3162,15 @@ pub fn linkerUpdateContainerType(pt: Zcu.PerThread, ty: InternPool.Index) !void
31523162
}
31533163
}
31543164

3165+
pub fn linkerUpdateLineNumber(pt: Zcu.PerThread, ti: InternPool.TrackedInst.Index) !void {
3166+
if (pt.zcu.comp.bin_file) |lf| {
3167+
lf.updateLineNumber(pt, ti) catch |err| switch (err) {
3168+
error.OutOfMemory => return error.OutOfMemory,
3169+
else => |e| log.err("update line number failed: {s}", .{@errorName(e)}),
3170+
};
3171+
}
3172+
}
3173+
31553174
pub fn reportRetryableAstGenError(
31563175
pt: Zcu.PerThread,
31573176
src: Zcu.AstGenSrc,

src/link.zig

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -727,16 +727,22 @@ pub const File = struct {
727727
}
728728
}
729729

730-
pub fn updateNavLineNumber(
731-
base: *File,
732-
pt: Zcu.PerThread,
733-
nav_index: InternPool.Nav.Index,
734-
) UpdateNavError!void {
730+
/// On an incremental update, fixup the line number of all `Nav`s at the given `TrackedInst`, because
731+
/// its line number has changed. The ZIR instruction `ti_id` has tag `.declaration`.
732+
pub fn updateLineNumber(base: *File, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) UpdateNavError!void {
733+
{
734+
const ti = ti_id.resolveFull(&pt.zcu.intern_pool).?;
735+
const file = pt.zcu.fileByIndex(ti.file);
736+
assert(file.zir_loaded);
737+
const inst = file.zir.instructions.get(@intFromEnum(ti.inst));
738+
assert(inst.tag == .declaration);
739+
}
740+
735741
switch (base.tag) {
736742
.spirv, .nvptx => {},
737743
inline else => |tag| {
738744
dev.check(tag.devFeature());
739-
return @as(*tag.Type(), @fieldParentPtr("base", base)).updateNavineNumber(pt, nav_index);
745+
return @as(*tag.Type(), @fieldParentPtr("base", base)).updateLineNumber(pt, ti_id);
740746
},
741747
}
742748
}
@@ -1407,6 +1413,8 @@ pub const Task = union(enum) {
14071413
codegen_func: CodegenFunc,
14081414
codegen_type: InternPool.Index,
14091415

1416+
update_line_number: InternPool.TrackedInst.Index,
1417+
14101418
pub const CodegenFunc = struct {
14111419
/// This will either be a non-generic `func_decl` or a `func_instance`.
14121420
func: InternPool.Index,
@@ -1558,6 +1566,13 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {
15581566
error.OutOfMemory => diags.setAllocFailure(),
15591567
};
15601568
},
1569+
.update_line_number => |ti| {
1570+
const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
1571+
defer pt.deactivate();
1572+
pt.linkerUpdateLineNumber(ti) catch |err| switch (err) {
1573+
error.OutOfMemory => diags.setAllocFailure(),
1574+
};
1575+
},
15611576
}
15621577
}
15631578

src/link/C.zig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -379,12 +379,12 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !
379379
gop.value_ptr.fwd_decl = try self.addString(object.dg.fwd_decl.items);
380380
}
381381

382-
pub fn updateNavLineNumber(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {
382+
pub fn updateLineNumber(self: *C, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {
383383
// The C backend does not have the ability to fix line numbers without re-generating
384384
// the entire Decl.
385385
_ = self;
386386
_ = pt;
387-
_ = nav_index;
387+
_ = ti_id;
388388
}
389389

390390
pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void {

src/link/Coff.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2484,11 +2484,11 @@ pub fn getGlobalSymbol(coff: *Coff, name: []const u8, lib_name_name: ?[]const u8
24842484
return global_index;
24852485
}
24862486

2487-
pub fn updateDeclLineNumber(coff: *Coff, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !void {
2487+
pub fn updateLineNumber(coff: *Coff, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {
24882488
_ = coff;
24892489
_ = pt;
2490-
_ = decl_index;
2491-
log.debug("TODO implement updateDeclLineNumber", .{});
2490+
_ = ti_id;
2491+
log.debug("TODO implement updateLineNumber", .{});
24922492
}
24932493

24942494
/// TODO: note if we need to rewrite base relocations by dirtying any of the entries in the global table

src/link/Dwarf.zig

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4156,21 +4156,11 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP
41564156
}
41574157
}
41584158

4159-
pub fn updateNavLineNumber(dwarf: *Dwarf, zcu: *Zcu, nav_index: InternPool.Nav.Index) UpdateError!void {
4160-
const ip = &zcu.intern_pool;
4161-
4162-
const zir_index = ip.getCau(ip.getNav(nav_index).analysis_owner.unwrap() orelse return).zir_index;
4163-
const inst_info = zir_index.resolveFull(ip).?;
4164-
assert(inst_info.inst != .main_struct_inst);
4165-
const file = zcu.fileByIndex(inst_info.file);
4166-
4167-
const line = file.zir.getDeclaration(inst_info.inst).src_line;
4168-
var line_buf: [4]u8 = undefined;
4169-
std.mem.writeInt(u32, &line_buf, line, dwarf.endian);
4170-
4171-
const unit = dwarf.debug_line.section.getUnit(dwarf.mods.get(file.mod).?);
4172-
const entry = unit.getEntry(dwarf.navs.get(nav_index).?);
4173-
try dwarf.getFile().?.pwriteAll(&line, dwarf.debug_line.section.off + unit.off + unit.header_len + entry.off + DebugInfo.declEntryLineOff(dwarf));
4159+
pub fn updateLineNumber(dwarf: *Dwarf, zcu: *Zcu, ti_id: InternPool.TrackedInst.Index) UpdateError!void {
4160+
_ = dwarf;
4161+
_ = zcu;
4162+
_ = ti_id;
4163+
@panic("TODO: Dwarf.updateLineNumber");
41744164
}
41754165

41764166
pub fn freeNav(dwarf: *Dwarf, nav_index: InternPool.Nav.Index) void {

src/link/Elf.zig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2372,9 +2372,9 @@ pub fn updateExports(
23722372
return self.zigObjectPtr().?.updateExports(self, pt, exported, export_indices);
23732373
}
23742374

2375-
pub fn updateNavLineNumber(self: *Elf, pt: Zcu.PerThread, nav: InternPool.Nav.Index) !void {
2375+
pub fn updateLineNumber(self: *Elf, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {
23762376
if (self.llvm_object) |_| return;
2377-
return self.zigObjectPtr().?.updateNavLineNumber(pt, nav);
2377+
return self.zigObjectPtr().?.updateLineNumber(pt, ti_id);
23782378
}
23792379

23802380
pub fn deleteExport(

src/link/Elf/ZigObject.zig

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1863,22 +1863,9 @@ pub fn updateExports(
18631863
}
18641864
}
18651865

1866-
/// Must be called only after a successful call to `updateNav`.
1867-
pub fn updateNavLineNumber(
1868-
self: *ZigObject,
1869-
pt: Zcu.PerThread,
1870-
nav_index: InternPool.Nav.Index,
1871-
) !void {
1872-
const tracy = trace(@src());
1873-
defer tracy.end();
1874-
1875-
const ip = &pt.zcu.intern_pool;
1876-
const nav = ip.getNav(nav_index);
1877-
1878-
log.debug("updateNavLineNumber {}({d})", .{ nav.fqn.fmt(ip), nav_index });
1879-
1866+
pub fn updateLineNumber(self: *ZigObject, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {
18801867
if (self.dwarf) |*dwarf| {
1881-
try dwarf.updateNavLineNumber(pt.zcu, nav_index);
1868+
try dwarf.updateLineNumber(pt.zcu, ti_id);
18821869
}
18831870
}
18841871

src/link/MachO.zig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3014,9 +3014,9 @@ pub fn updateNav(self: *MachO, pt: Zcu.PerThread, nav: InternPool.Nav.Index) !vo
30143014
return self.getZigObject().?.updateNav(self, pt, nav);
30153015
}
30163016

3017-
pub fn updateNavLineNumber(self: *MachO, pt: Zcu.PerThread, nav: InternPool.NavIndex) !void {
3017+
pub fn updateLineNumber(self: *MachO, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {
30183018
if (self.llvm_object) |_| return;
3019-
return self.getZigObject().?.updateNavLineNumber(pt, nav);
3019+
return self.getZigObject().?.updateLineNumber(pt, ti_id);
30203020
}
30213021

30223022
pub fn updateExports(

0 commit comments

Comments
 (0)