authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-06-16 00:22:17-04:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-06-23 00:27:18-04:00
log411e5099e5fb8a8e1b39e0bcd0098e7a2c162aec
treeaf62de07a424afd191244361f556ea1d9bc8944b
parentc9601664c6914a8bdbf778f494a0a4fe6d84fa53

link: remove debug_link_snapshots in favour of enable_debug_extensions

MappedFile: use opts struct for realign Coff: fixup not reserving enough string capacity in loadObject

7 files changed, 40 insertions(+), 38 deletions(-)

build.zig-3
......@@ -256,7 +256,6 @@ pub fn build(b: *std.Build) !void {
256256 const is_debug = optimize == .Debug;
257257 const enable_debug_extensions = b.option(bool, "debug-extensions", "Enable commands and options useful for debugging the compiler") orelse is_debug;
258258 const enable_logging = b.option(bool, "log", "Enable debug logging with --debug-log") orelse is_debug;
259 const enable_link_snapshots = b.option(bool, "link-snapshot", "Whether to enable linker state snapshots") orelse false;
260259
261260 const opt_version_string = b.option([]const u8, "version-string", "Override Zig version string. Default is to find out with git.");
262261 const version_slice = if (opt_version_string) |version| version else v: {
......@@ -372,7 +371,6 @@ pub fn build(b: *std.Build) !void {
372371
373372 exe_options.addOption(bool, "enable_debug_extensions", enable_debug_extensions);
374373 exe_options.addOption(bool, "enable_logging", enable_logging);
375 exe_options.addOption(bool, "enable_link_snapshots", enable_link_snapshots);
376374 exe_options.addOption(bool, "enable_tracy", tracy != null);
377375 exe_options.addOption(bool, "enable_tracy_callstack", tracy_callstack);
378376 exe_options.addOption(bool, "enable_tracy_allocation", tracy_allocation);
......@@ -733,7 +731,6 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {
733731 exe_options.addOption(std.SemanticVersion, "semver", semver);
734732 exe_options.addOption(bool, "enable_debug_extensions", false);
735733 exe_options.addOption(bool, "enable_logging", false);
736 exe_options.addOption(bool, "enable_link_snapshots", false);
737734 exe_options.addOption(bool, "enable_tracy", false);
738735 exe_options.addOption(bool, "enable_tracy_callstack", false);
739736 exe_options.addOption(bool, "enable_tracy_allocation", false);
src/crash_report.zig+5-8
......@@ -132,14 +132,11 @@ fn dumpCrashContext() Io.Writer.Error!void {
132132 try dumpCrashContextSema(anal, w, &S.crash_heap);
133133 } else if (LinkerOp.current) |linker_op| {
134134 try w.writeAll("Linker snapshot:\n");
135 if (build_options.enable_link_snapshots) {
136 switch (try linker_op.lf.dump(w, linker_op.tid)) {
137 .unsupported => try w.writeAll("(backend does not support link snapshots)"),
138 .disabled => try w.writeAll("(run with --debug-link-snapshot to dump linker state)"),
139 .enabled => {},
140 }
141 } else {
142 try w.writeAll("(build with -Dlink-snapshot to dump linker state)");
135 switch (try linker_op.lf.dump(w, linker_op.tid)) {
136 .unimplemented => try w.writeAll("(backend does not support link snapshots)"),
137 .needs_extensions => try w.writeAll("(build with -Ddebug-extensions to dump linker state)"),
138 .disabled => try w.writeAll("(run with --debug-link-snapshot to dump linker state)"),
139 .enabled => {},
143140 }
144141 try w.writeAll("\n\n");
145142 } else {
src/link.zig+4-3
......@@ -1091,13 +1091,14 @@ pub const File = struct {
10911091 }
10921092
10931093 pub const DumpResult = enum {
1094 unsupported,
1094 unimplemented,
1095 needs_extensions,
10951096 disabled,
10961097 enabled,
10971098 };
10981099
10991100 pub fn dump(base: *File, w: *Io.Writer, tid: Zcu.PerThread.Id) !DumpResult {
1100 if (!build_options.enable_link_snapshots) unreachable;
1101 if (!build_options.enable_debug_extensions) return .not_built;
11011102 switch (base.tag) {
11021103 .elf,
11031104 .macho,
......@@ -1106,7 +1107,7 @@ pub const File = struct {
11061107 .spirv,
11071108 .plan9,
11081109 .lld,
1109 => return .unsupported,
1110 => return .unimplemented,
11101111 inline else => |tag| {
11111112 dev.check(tag.devFeature());
11121113 return @as(*tag.Type(), @fieldParentPtr("base", base)).dump(w, tid);
src/link/Coff.zig+9-7
......@@ -22,6 +22,7 @@ const implib = @import("../libs/mingw/implib.zig");
2222const Path = std.Build.Cache.Path;
2323
2424base: link.File,
25options: link.File.OpenOptions,
2526mf: MappedFile,
2627nodes: std.MultiArrayList(Node),
2728members: std.ArrayList(Member),
......@@ -82,7 +83,6 @@ synth_prog_node: std.Progress.Node,
8283symbol_prog_node: std.Progress.Node,
8384member_prog_node: std.Progress.Node,
8485input_prog_node: std.Progress.Node,
85dump_snapshot: bool,
8686
8787pub const default_file_alignment: u16 = 0x200;
8888pub const default_size_of_stack_reserve: u32 = 0x1000000;
......@@ -1593,6 +1593,7 @@ fn create(
15931593 .allow_shlib_undefined = false,
15941594 .stack_size = 0,
15951595 },
1596 .options = options,
15961597 .mf = try .init(file, comp.gpa, io),
15971598 .nodes = .empty,
15981599 .members = .empty,
......@@ -1664,7 +1665,6 @@ fn create(
16641665 .symbol_prog_node = .none,
16651666 .member_prog_node = .none,
16661667 .input_prog_node = .none,
1667 .dump_snapshot = options.enable_link_snapshots,
16681668 };
16691669 errdefer coff.deinit();
16701670
......@@ -3579,13 +3579,13 @@ fn objectSectionMapIndex(
35793579 const parent_alignment = parent_ni.alignment(&coff.mf);
35803580 if (alignment.compare(.gt, parent_alignment)) {
35813581 log.debug("realignParent({s}, {d}) {d}->{d}", .{ name.toSlice(coff), parent_ni, parent_alignment, alignment });
3582 try parent_ni.realign(&coff.mf, gpa, alignment, true);
3582 try parent_ni.realign(&coff.mf, gpa, alignment, .{ .set_alignment = true });
35833583 }
35843584
35853585 const old_alignment = sym.ni.alignment(&coff.mf);
35863586 if (alignment.compare(.gt, old_alignment)) {
35873587 log.debug("realignObject({s}) {d}->{d}", .{ name.toSlice(coff), old_alignment, alignment });
3588 try sym.ni.realign(&coff.mf, gpa, alignment, true);
3588 try sym.ni.realign(&coff.mf, gpa, alignment, .{ .set_alignment = true });
35893589 }
35903590
35913591 try coff.verifyParentSectionAttributes(
......@@ -3980,7 +3980,9 @@ fn loadObject(
39803980
39813981 try coff.ensureManyUnusedStringCapacity(
39823982 header.number_of_sections + header.number_of_symbols,
3983 string_table_len - @sizeOf(u32),
3983 header.number_of_sections * 9 +
3984 header.number_of_symbols * 9 +
3985 string_table_len - @sizeOf(u32),
39843986 );
39853987
39863988 const PendingSymbolIndex = enum(u32) {
......@@ -5886,7 +5888,7 @@ pub fn flush(
58865888 else => |e| return comp.link_diags.fail("flush write failed: {t}", .{e}),
58875889 };
58885890
5889 if (coff.dump_snapshot)
5891 if (coff.options.enable_link_snapshots)
58905892 coff.dumpStderr(tid) catch |err|
58915893 return comp.link_diags.fail("dumping link snapshot failed: {t}", .{err});
58925894}
......@@ -7534,7 +7536,7 @@ fn dumpStderr(coff: *Coff, tid: Zcu.PerThread.Id) !void {
75347536}
75357537
75367538pub fn dump(coff: *Coff, w: *Io.Writer, tid: Zcu.PerThread.Id) !link.File.DumpResult {
7537 if (coff.dump_snapshot) {
7539 if (coff.options.enable_link_snapshots) {
75387540 try coff.printNode(tid, w, .root, 0);
75397541 try w.writeAll("Section table:\n");
75407542 for (coff.section_table.keys(), coff.section_table.values()) |name, sec|
src/link/Elf2.zig+4-6
......@@ -161,7 +161,6 @@ textrel_count: u32,
161161const_prog_node: std.Progress.Node,
162162synth_prog_node: std.Progress.Node,
163163input_prog_node: std.Progress.Node,
164dump_snapshot: bool,
165164
166165const Error = link.Error || error{MappedFileIo};
167166
......@@ -2625,7 +2624,6 @@ fn create(
26252624 .synth_prog_node = .none,
26262625 .input_prog_node = .none,
26272626 .textrel_count = 0,
2628 .dump_snapshot = options.enable_link_snapshots,
26292627 };
26302628 errdefer elf.deinit();
26312629
......@@ -3787,7 +3785,7 @@ fn mapInputSection(elf: *Elf, opts: struct {
37873785 const new_alignment: std.mem.Alignment = .fromByteUnits(
37883786 std.math.ceilPowerOfTwoAssert(usize, @intCast(opts.addralign)),
37893787 );
3790 try existing_shndx.get(elf).ni.realign(&elf.mf, gpa, new_alignment, true);
3788 try existing_shndx.get(elf).ni.realign(&elf.mf, gpa, new_alignment, .{ .set_alignment = true });
37913789 }
37923790 // ...and update the shdr as needed.
37933791 switch (elf.shdrPtr(existing_shndx)) {
......@@ -3950,7 +3948,7 @@ fn uavMapIndex(
39503948 } else {
39513949 const node = uav_gop.value_ptr.lsi.index().ptr(elf).node;
39523950 if (resolved_align.toStdMem().order(node.alignment(&elf.mf)).compare(.gt)) {
3953 try node.realign(&elf.mf, gpa, resolved_align.toStdMem(), true);
3951 try node.realign(&elf.mf, gpa, resolved_align.toStdMem(), .{ .set_alignment = true });
39543952 }
39553953 }
39563954 return umi;
......@@ -4679,7 +4677,7 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (LoadPars
46794677 // We have a copy relocation for this global, but the amount of space we
46804678 // reserved for it could be too small or underaligned!
46814679 try copied_global.node.resize(&elf.mf, gpa, gop.value_ptr.size);
4682 try copied_global.node.realign(&elf.mf, gpa, gop.value_ptr.alignment, true);
4680 try copied_global.node.realign(&elf.mf, gpa, gop.value_ptr.alignment, .{ .set_alignment = true });
46834681 const global_ptr = elf.globalByName(name).?;
46844682 switch (elf.symPtr(global_ptr.symtab_index)) {
46854683 inline else => |sym_ptr| elf.targetStore(&sym_ptr.size, @intCast(gop.value_ptr.size)),
......@@ -6714,7 +6712,7 @@ pub fn deleteExport(elf: *Elf, exported: Zcu.Exported, name: InternPool.NullTerm
67146712}
67156713
67166714pub fn dump(elf: *Elf, w: *Io.Writer, tid: Zcu.PerThread.Id) !link.File.DumpResult {
6717 if (elf.dump_snapshot) {
6715 if (elf.options.enable_link_snapshots) {
67186716 try elf.printNode(tid, w, .root, 0);
67196717 return .enabled;
67206718 }
src/link/MappedFile.zig+16-9
......@@ -354,18 +354,23 @@ pub const Node = extern struct {
354354 }
355355 }
356356
357 pub const RealignNodeOptions = struct {
358 /// Shift the node backwards if possible
359 try_backwards: bool = true,
360 /// If `set, persists `new_alignment` as the node's alignment for future operations.
361 set_alignment: bool = true,
362 };
363
357364 /// Moves and expands a node such that its offset and size are aligned to `new_alignment`.
358 /// If it is possible to move the node backwards, this will be done instead of moving it forward.
359 /// If `set_alignment` is set, persists `new_alignment` as the node's alignment for future operations.
360365 /// Asserts that `ni` is not `Node.Index.root`.
361366 pub fn realign(
362367 ni: Node.Index,
363368 mf: *MappedFile,
364369 gpa: std.mem.Allocator,
365370 new_alignment: std.mem.Alignment,
366 set_alignment: bool,
371 opts: RealignNodeOptions,
367372 ) Error!void {
368 mf.realignNode(gpa, ni, new_alignment, true, set_alignment) catch |err| switch (err) {
373 mf.realignNode(gpa, ni, new_alignment, opts) catch |err| switch (err) {
369374 error.OutOfMemory,
370375 error.Canceled,
371376 => |e| return e,
......@@ -573,7 +578,10 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {
573578 else => |next_ni| {
574579 const next_offset, _ = next_ni.location(mf).resolve(mf);
575580 if (new_end > next_offset)
576 try next_ni.realign(mf, gpa, opts.add_node.alignment, false);
581 try next_ni.realign(mf, gpa, opts.add_node.alignment, .{
582 .try_backwards = false,
583 .set_alignment = false,
584 });
577585 },
578586 }
579587 }
......@@ -1035,8 +1043,7 @@ fn realignNode(
10351043 gpa: std.mem.Allocator,
10361044 ni: Node.Index,
10371045 new_alignment: std.mem.Alignment,
1038 try_backward: bool,
1039 set_alignment: bool,
1046 opts: Node.Index.RealignNodeOptions,
10401047) (Allocator.Error || Io.Cancelable || IoError)!void {
10411048 assert(ni != Node.Index.root); // currently unsupported
10421049 mf.nodes_lock.assertUnlocked();
......@@ -1052,7 +1059,7 @@ fn realignNode(
10521059 node.flags.alignment = new_alignment;
10531060 defer {
10541061 // alignment needs to be temporarily set for the resizes below
1055 if (!set_alignment) node.flags.alignment = prev_alignment;
1062 if (!opts.set_alignment) node.flags.alignment = prev_alignment;
10561063 }
10571064
10581065 const new_size = node.flags.alignment.forward(@intCast(size));
......@@ -1070,7 +1077,7 @@ fn realignNode(
10701077 },
10711078 };
10721079
1073 if (try_backward) {
1080 if (opts.try_backwards) {
10741081 const backward_offset = new_alignment.backward(@intCast(old_offset));
10751082 const prev_end = if (node.prev == .none) 0 else prev: {
10761083 const prev_offset, const prev_size = node.prev.location(mf).resolve(mf);
src/main.zig+2-2
......@@ -1440,8 +1440,8 @@ fn buildOutputType(
14401440 dev.check(.stdio_listen);
14411441 listen = .stdio;
14421442 } else if (mem.eql(u8, arg, "--debug-link-snapshot")) {
1443 if (!build_options.enable_link_snapshots) {
1444 warn("Zig was compiled without linker snapshots enabled (-Dlink-snapshot). --debug-link-snapshot has no effect.", .{});
1443 if (!build_options.enable_debug_extensions) {
1444 warn("Zig was compiled without debug extensions. --debug-link-snapshot has no effect.", .{});
14451445 } else {
14461446 enable_link_snapshots = true;
14471447 }