authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-01-01 20:16:48+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-01-05 02:20:56+00:00
log065e10c95ccca509afecfecc849da9114e0000b2
treebd1c4bee8e3da377fa1da9254b442900c538a45d
parent136c5a916ed7e421461ac5839cc0e4c289b80f16
signaturelock-open Commit is signed but in an unrecognized format.

link: new incremental line number update API


14 files changed, 90 insertions(+), 71 deletions(-)

change_line_number created+16
......@@ -0,0 +1,16 @@
1#target=x86_64-linux-selfhosted
2#update=initial version
3#file=main.zig
4const std = @import("std");
5pub 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
11const std = @import("std");
12
13pub fn main() !void {
14 try std.io.getStdOut().writeAll("foo\n");
15}
16#expect_stdout="foo\n"
src/Compilation.zig+4
......@@ -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+25-6
......@@ -379,6 +379,7 @@ fn cleanupUpdatedFiles(gpa: Allocator, updated_files: *std.AutoArrayHashMapUnman
379379pub 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
3165pub 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
31553174pub fn reportRetryableAstGenError(
31563175 pt: Zcu.PerThread,
31573176 src: Zcu.AstGenSrc,
src/link.zig+21-6
......@@ -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+2-2
......@@ -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
382pub fn updateNavLineNumber(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {
382pub 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
390390pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void {
src/link/Coff.zig+3-3
......@@ -2484,11 +2484,11 @@ pub fn getGlobalSymbol(coff: *Coff, name: []const u8, lib_name_name: ?[]const u8
24842484 return global_index;
24852485}
24862486
2487pub fn updateDeclLineNumber(coff: *Coff, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !void {
2487pub 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+5-15
......@@ -4156,21 +4156,11 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP
41564156 }
41574157}
41584158
4159pub 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));
4159pub 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
41764166pub fn freeNav(dwarf: *Dwarf, nav_index: InternPool.Nav.Index) void {
src/link/Elf.zig+2-2
......@@ -2372,9 +2372,9 @@ pub fn updateExports(
23722372 return self.zigObjectPtr().?.updateExports(self, pt, exported, export_indices);
23732373}
23742374
2375pub fn updateNavLineNumber(self: *Elf, pt: Zcu.PerThread, nav: InternPool.Nav.Index) !void {
2375pub 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
23802380pub fn deleteExport(
src/link/Elf/ZigObject.zig+2-15
......@@ -1863,22 +1863,9 @@ pub fn updateExports(
18631863 }
18641864}
18651865
1866/// Must be called only after a successful call to `updateNav`.
1867pub 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
1866pub 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+2-2
......@@ -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
3017pub fn updateNavLineNumber(self: *MachO, pt: Zcu.PerThread, nav: InternPool.NavIndex) !void {
3017pub 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
30223022pub fn updateExports(
src/link/MachO/ZigObject.zig+2-7
......@@ -1432,14 +1432,9 @@ fn updateLazySymbol(
14321432 try macho_file.base.file.?.pwriteAll(code, file_offset);
14331433}
14341434
1435/// Must be called only after a successful call to `updateNav`.
1436pub fn updateNavLineNumber(
1437 self: *ZigObject,
1438 pt: Zcu.PerThread,
1439 nav_index: InternPool.Nav.Index,
1440) !void {
1435pub fn updateLineNumber(self: *ZigObject, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {
14411436 if (self.dwarf) |*dwarf| {
1442 try dwarf.updateNavLineNumber(pt.zcu, nav_index);
1437 try dwarf.updateLineNumber(pt.zcu, ti_id);
14431438 }
14441439}
14451440
src/link/Plan9.zig+2-3
......@@ -1354,11 +1354,10 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {
13541354 }
13551355}
13561356
1357/// Must be called only after a successful call to `updateDecl`.
1358pub fn updateDeclLineNumber(self: *Plan9, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !void {
1357pub fn updateLineNumber(self: *Plan9, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {
13591358 _ = self;
13601359 _ = pt;
1361 _ = decl_index;
1360 _ = ti_id;
13621361}
13631362
13641363pub fn getNavVAddr(
src/link/Wasm.zig+2-2
......@@ -1574,9 +1574,9 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav: InternPool.Nav.Index) !voi
15741574 try wasm.zig_object.?.updateNav(wasm, pt, nav);
15751575}
15761576
1577pub fn updateNavLineNumber(wasm: *Wasm, pt: Zcu.PerThread, nav: InternPool.Nav.Index) !void {
1577pub fn updateLineNumber(wasm: *Wasm, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {
15781578 if (wasm.llvm_object) |_| return;
1579 try wasm.zig_object.?.updateNavLineNumber(pt, nav);
1579 try wasm.zig_object.?.updateLineNumber(pt, ti_id);
15801580}
15811581
15821582/// From a given symbol location, returns its `wasm.GlobalType`.
src/link/Wasm/ZigObject.zig+2-8
......@@ -1074,15 +1074,9 @@ pub fn createDebugSectionForIndex(zig_object: *ZigObject, wasm: *Wasm, index: *?
10741074 return atom_index;
10751075}
10761076
1077pub fn updateDeclLineNumber(
1078 zig_object: *ZigObject,
1079 pt: Zcu.PerThread,
1080 decl_index: InternPool.DeclIndex,
1081) !void {
1077pub fn updateLineNumber(zig_object: *ZigObject, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {
10821078 if (zig_object.dwarf) |*dw| {
1083 const decl = pt.zcu.declPtr(decl_index);
1084 log.debug("updateDeclLineNumber {}{*}", .{ decl.fqn.fmt(&pt.zcu.intern_pool), decl });
1085 try dw.updateDeclLineNumber(pt.zcu, decl_index);
1079 try dw.updateLineNumber(pt.zcu, ti_id);
10861080 }
10871081}
10881082