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:
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;
}