zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 411e5099e5fb8a8e1b39e0bcd0098e7a2c162aec (tree)
parent c9601664c6914a8bdbf778f494a0a4fe6d84fa53
Author: kcbanner <kcbanner@gmail.com>
Date:   Tue, 16 Jun 2026 00:22:17 -0400

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

Diffstat:
Mbuild.zig | 3---
Msrc/crash_report.zig | 13+++++--------
Msrc/link.zig | 7++++---
Msrc/link/Coff.zig | 16+++++++++-------
Msrc/link/Elf2.zig | 10++++------
Msrc/link/MappedFile.zig | 25++++++++++++++++---------
Msrc/main.zig | 4++--
7 files changed, 40 insertions(+), 38 deletions(-)

diff --git a/build.zig b/build.zig @@ -256,7 +256,6 @@ pub fn build(b: *std.Build) !void { const is_debug = optimize == .Debug; const enable_debug_extensions = b.option(bool, "debug-extensions", "Enable commands and options useful for debugging the compiler") orelse is_debug; const enable_logging = b.option(bool, "log", "Enable debug logging with --debug-log") orelse is_debug; - const enable_link_snapshots = b.option(bool, "link-snapshot", "Whether to enable linker state snapshots") orelse false; const opt_version_string = b.option([]const u8, "version-string", "Override Zig version string. Default is to find out with git."); const version_slice = if (opt_version_string) |version| version else v: { @@ -372,7 +371,6 @@ pub fn build(b: *std.Build) !void { exe_options.addOption(bool, "enable_debug_extensions", enable_debug_extensions); exe_options.addOption(bool, "enable_logging", enable_logging); - exe_options.addOption(bool, "enable_link_snapshots", enable_link_snapshots); exe_options.addOption(bool, "enable_tracy", tracy != null); exe_options.addOption(bool, "enable_tracy_callstack", tracy_callstack); exe_options.addOption(bool, "enable_tracy_allocation", tracy_allocation); @@ -733,7 +731,6 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void { exe_options.addOption(std.SemanticVersion, "semver", semver); exe_options.addOption(bool, "enable_debug_extensions", false); exe_options.addOption(bool, "enable_logging", false); - exe_options.addOption(bool, "enable_link_snapshots", false); exe_options.addOption(bool, "enable_tracy", false); exe_options.addOption(bool, "enable_tracy_callstack", false); exe_options.addOption(bool, "enable_tracy_allocation", false); diff --git a/src/crash_report.zig b/src/crash_report.zig @@ -132,14 +132,11 @@ fn dumpCrashContext() Io.Writer.Error!void { try dumpCrashContextSema(anal, w, &S.crash_heap); } else if (LinkerOp.current) |linker_op| { try w.writeAll("Linker snapshot:\n"); - if (build_options.enable_link_snapshots) { - switch (try linker_op.lf.dump(w, linker_op.tid)) { - .unsupported => try w.writeAll("(backend does not support link snapshots)"), - .disabled => try w.writeAll("(run with --debug-link-snapshot to dump linker state)"), - .enabled => {}, - } - } else { - try w.writeAll("(build with -Dlink-snapshot to dump linker state)"); + switch (try linker_op.lf.dump(w, linker_op.tid)) { + .unimplemented => try w.writeAll("(backend does not support link snapshots)"), + .needs_extensions => try w.writeAll("(build with -Ddebug-extensions to dump linker state)"), + .disabled => try w.writeAll("(run with --debug-link-snapshot to dump linker state)"), + .enabled => {}, } try w.writeAll("\n\n"); } else { diff --git a/src/link.zig b/src/link.zig @@ -1091,13 +1091,14 @@ pub const File = struct { } pub const DumpResult = enum { - unsupported, + unimplemented, + needs_extensions, disabled, enabled, }; pub fn dump(base: *File, w: *Io.Writer, tid: Zcu.PerThread.Id) !DumpResult { - if (!build_options.enable_link_snapshots) unreachable; + if (!build_options.enable_debug_extensions) return .not_built; switch (base.tag) { .elf, .macho, @@ -1106,7 +1107,7 @@ pub const File = struct { .spirv, .plan9, .lld, - => return .unsupported, + => return .unimplemented, inline else => |tag| { dev.check(tag.devFeature()); return @as(*tag.Type(), @fieldParentPtr("base", base)).dump(w, tid); diff --git a/src/link/Coff.zig b/src/link/Coff.zig @@ -22,6 +22,7 @@ const implib = @import("../libs/mingw/implib.zig"); const Path = std.Build.Cache.Path; base: link.File, +options: link.File.OpenOptions, mf: MappedFile, nodes: std.MultiArrayList(Node), members: std.ArrayList(Member), @@ -82,7 +83,6 @@ synth_prog_node: std.Progress.Node, symbol_prog_node: std.Progress.Node, member_prog_node: std.Progress.Node, input_prog_node: std.Progress.Node, -dump_snapshot: bool, pub const default_file_alignment: u16 = 0x200; pub const default_size_of_stack_reserve: u32 = 0x1000000; @@ -1593,6 +1593,7 @@ fn create( .allow_shlib_undefined = false, .stack_size = 0, }, + .options = options, .mf = try .init(file, comp.gpa, io), .nodes = .empty, .members = .empty, @@ -1664,7 +1665,6 @@ fn create( .symbol_prog_node = .none, .member_prog_node = .none, .input_prog_node = .none, - .dump_snapshot = options.enable_link_snapshots, }; errdefer coff.deinit(); @@ -3579,13 +3579,13 @@ fn objectSectionMapIndex( const parent_alignment = parent_ni.alignment(&coff.mf); if (alignment.compare(.gt, parent_alignment)) { log.debug("realignParent({s}, {d}) {d}->{d}", .{ name.toSlice(coff), parent_ni, parent_alignment, alignment }); - try parent_ni.realign(&coff.mf, gpa, alignment, true); + try parent_ni.realign(&coff.mf, gpa, alignment, .{ .set_alignment = true }); } const old_alignment = sym.ni.alignment(&coff.mf); if (alignment.compare(.gt, old_alignment)) { log.debug("realignObject({s}) {d}->{d}", .{ name.toSlice(coff), old_alignment, alignment }); - try sym.ni.realign(&coff.mf, gpa, alignment, true); + try sym.ni.realign(&coff.mf, gpa, alignment, .{ .set_alignment = true }); } try coff.verifyParentSectionAttributes( @@ -3980,7 +3980,9 @@ fn loadObject( try coff.ensureManyUnusedStringCapacity( header.number_of_sections + header.number_of_symbols, - string_table_len - @sizeOf(u32), + header.number_of_sections * 9 + + header.number_of_symbols * 9 + + string_table_len - @sizeOf(u32), ); const PendingSymbolIndex = enum(u32) { @@ -5886,7 +5888,7 @@ pub fn flush( else => |e| return comp.link_diags.fail("flush write failed: {t}", .{e}), }; - if (coff.dump_snapshot) + if (coff.options.enable_link_snapshots) coff.dumpStderr(tid) catch |err| return comp.link_diags.fail("dumping link snapshot failed: {t}", .{err}); } @@ -7534,7 +7536,7 @@ fn dumpStderr(coff: *Coff, tid: Zcu.PerThread.Id) !void { } pub fn dump(coff: *Coff, w: *Io.Writer, tid: Zcu.PerThread.Id) !link.File.DumpResult { - if (coff.dump_snapshot) { + if (coff.options.enable_link_snapshots) { try coff.printNode(tid, w, .root, 0); try w.writeAll("Section table:\n"); for (coff.section_table.keys(), coff.section_table.values()) |name, sec| diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig @@ -161,7 +161,6 @@ textrel_count: u32, const_prog_node: std.Progress.Node, synth_prog_node: std.Progress.Node, input_prog_node: std.Progress.Node, -dump_snapshot: bool, const Error = link.Error || error{MappedFileIo}; @@ -2625,7 +2624,6 @@ fn create( .synth_prog_node = .none, .input_prog_node = .none, .textrel_count = 0, - .dump_snapshot = options.enable_link_snapshots, }; errdefer elf.deinit(); @@ -3787,7 +3785,7 @@ fn mapInputSection(elf: *Elf, opts: struct { const new_alignment: std.mem.Alignment = .fromByteUnits( std.math.ceilPowerOfTwoAssert(usize, @intCast(opts.addralign)), ); - try existing_shndx.get(elf).ni.realign(&elf.mf, gpa, new_alignment, true); + try existing_shndx.get(elf).ni.realign(&elf.mf, gpa, new_alignment, .{ .set_alignment = true }); } // ...and update the shdr as needed. switch (elf.shdrPtr(existing_shndx)) { @@ -3950,7 +3948,7 @@ fn uavMapIndex( } else { const node = uav_gop.value_ptr.lsi.index().ptr(elf).node; if (resolved_align.toStdMem().order(node.alignment(&elf.mf)).compare(.gt)) { - try node.realign(&elf.mf, gpa, resolved_align.toStdMem(), true); + try node.realign(&elf.mf, gpa, resolved_align.toStdMem(), .{ .set_alignment = true }); } } return umi; @@ -4679,7 +4677,7 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (LoadPars // We have a copy relocation for this global, but the amount of space we // reserved for it could be too small or underaligned! try copied_global.node.resize(&elf.mf, gpa, gop.value_ptr.size); - try copied_global.node.realign(&elf.mf, gpa, gop.value_ptr.alignment, true); + try copied_global.node.realign(&elf.mf, gpa, gop.value_ptr.alignment, .{ .set_alignment = true }); const global_ptr = elf.globalByName(name).?; switch (elf.symPtr(global_ptr.symtab_index)) { 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 } pub fn dump(elf: *Elf, w: *Io.Writer, tid: Zcu.PerThread.Id) !link.File.DumpResult { - if (elf.dump_snapshot) { + if (elf.options.enable_link_snapshots) { try elf.printNode(tid, w, .root, 0); return .enabled; } diff --git a/src/link/MappedFile.zig b/src/link/MappedFile.zig @@ -354,18 +354,23 @@ pub const Node = extern struct { } } + pub const RealignNodeOptions = struct { + /// Shift the node backwards if possible + try_backwards: bool = true, + /// If `set, persists `new_alignment` as the node's alignment for future operations. + set_alignment: bool = true, + }; + /// Moves and expands a node such that its offset and size are aligned to `new_alignment`. - /// If it is possible to move the node backwards, this will be done instead of moving it forward. - /// If `set_alignment` is set, persists `new_alignment` as the node's alignment for future operations. /// Asserts that `ni` is not `Node.Index.root`. pub fn realign( ni: Node.Index, mf: *MappedFile, gpa: std.mem.Allocator, new_alignment: std.mem.Alignment, - set_alignment: bool, + opts: RealignNodeOptions, ) Error!void { - mf.realignNode(gpa, ni, new_alignment, true, set_alignment) catch |err| switch (err) { + mf.realignNode(gpa, ni, new_alignment, opts) catch |err| switch (err) { error.OutOfMemory, error.Canceled, => |e| return e, @@ -573,7 +578,10 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct { else => |next_ni| { const next_offset, _ = next_ni.location(mf).resolve(mf); if (new_end > next_offset) - try next_ni.realign(mf, gpa, opts.add_node.alignment, false); + try next_ni.realign(mf, gpa, opts.add_node.alignment, .{ + .try_backwards = false, + .set_alignment = false, + }); }, } } @@ -1035,8 +1043,7 @@ fn realignNode( gpa: std.mem.Allocator, ni: Node.Index, new_alignment: std.mem.Alignment, - try_backward: bool, - set_alignment: bool, + opts: Node.Index.RealignNodeOptions, ) (Allocator.Error || Io.Cancelable || IoError)!void { assert(ni != Node.Index.root); // currently unsupported mf.nodes_lock.assertUnlocked(); @@ -1052,7 +1059,7 @@ fn realignNode( node.flags.alignment = new_alignment; defer { // alignment needs to be temporarily set for the resizes below - if (!set_alignment) node.flags.alignment = prev_alignment; + if (!opts.set_alignment) node.flags.alignment = prev_alignment; } const new_size = node.flags.alignment.forward(@intCast(size)); @@ -1070,7 +1077,7 @@ fn realignNode( }, }; - if (try_backward) { + if (opts.try_backwards) { const backward_offset = new_alignment.backward(@intCast(old_offset)); const prev_end = if (node.prev == .none) 0 else prev: { const prev_offset, const prev_size = node.prev.location(mf).resolve(mf); diff --git a/src/main.zig b/src/main.zig @@ -1440,8 +1440,8 @@ fn buildOutputType( dev.check(.stdio_listen); listen = .stdio; } else if (mem.eql(u8, arg, "--debug-link-snapshot")) { - if (!build_options.enable_link_snapshots) { - warn("Zig was compiled without linker snapshots enabled (-Dlink-snapshot). --debug-link-snapshot has no effect.", .{}); + if (!build_options.enable_debug_extensions) { + warn("Zig was compiled without debug extensions. --debug-link-snapshot has no effect.", .{}); } else { enable_link_snapshots = true; }