authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-06-05 01:55:37-04:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-06-23 00:27:17-04:00
log1b74bc22e969e708d5ac6cb34a7b9cd069b71e80
tree028e0838d2d2f6a5673f922f791170f32dbdae2e
parent537d7b74274c31ea4240870724ffd41e0e5de8dd

Rebase fixups

- Fixup error sets / use the new linker error conventions - Improve snapshot diff output

7 files changed, 262 insertions(+), 111 deletions(-)

lib/compiler/Maker/Step/Run.zig+55-3
......@@ -2126,10 +2126,16 @@ fn runCommand(
21262126 defer gpa.free(snapshot_contents);
21272127
21282128 const result = switch (snapshot.result) {
2129 .stdout => generic_result.stdout.?,
21302129 .stderr => generic_result.stderr.?,
2130 .stdout => generic_result.stdout.?,
21312131 };
2132 if (!mem.eql(u8, snapshot_contents, result)) {
2132 if (std.mem.findDiff(u8, snapshot_contents, result)) |diff_index| {
2133 var diff_line_number: usize = 1;
2134
2135 for (snapshot_contents[0..diff_index]) |value| {
2136 if (value == '\n') diff_line_number += 1;
2137 }
2138
21332139 return step.fail(maker,
21342140 \\
21352141 \\========= snapshot file: =========
......@@ -2138,7 +2144,21 @@ fn runCommand(
21382144 \\{s}
21392145 \\========= {t} output was: ========
21402146 \\{s}
2141 , .{ snapshot.path, snapshot_contents, snapshot.result, result });
2147 \\==================================
2148 \\first difference on line {d}:
2149 \\expected:
2150 \\{f}
2151 \\found:
2152 \\{f}
2153 , .{
2154 snapshot.path,
2155 snapshot_contents,
2156 snapshot.result,
2157 result,
2158 diff_line_number,
2159 fmtSnapshotIndicatorLine(snapshot_contents, diff_index),
2160 fmtSnapshotIndicatorLine(result, diff_index),
2161 });
21422162 }
21432163 }
21442164 },
......@@ -2154,6 +2174,38 @@ fn runCommand(
21542174 }
21552175}
21562176
2177const FmtIndicatorLine = struct {
2178 buf: []const u8,
2179 index: usize,
2180};
2181
2182fn fmtSnapshotIndicatorLine(buf: []const u8, index: usize) std.fmt.Alt(
2183 FmtIndicatorLine,
2184 snapshotIndicatorLine,
2185) {
2186 return .{ .data = .{ .buf = buf, .index = index } };
2187}
2188
2189fn snapshotIndicatorLine(line: FmtIndicatorLine, w: *std.Io.Writer) std.Io.Writer.Error!void {
2190 const line_begin_index = if (std.mem.lastIndexOfScalar(u8, line.buf[0..line.index], '\n')) |line_begin|
2191 line_begin + 1
2192 else
2193 0;
2194 const line_end_index = if (std.mem.findScalar(u8, line.buf[line.index..], '\n')) |line_end|
2195 (line.index + line_end)
2196 else
2197 line.buf.len;
2198
2199 try w.writeAll(line.buf[line_begin_index..line_end_index]);
2200 try w.writeByte('\n');
2201 try w.splatByteAll(' ', line_end_index - line_begin_index);
2202 try w.writeByte('\n');
2203 if (line.index >= line.buf.len)
2204 try w.writeAll("^ (end of file)")
2205 else
2206 try w.print("^ ('\\x{x:0>2}')\n", .{line.buf[line.index]});
2207}
2208
21572209const EvalGenericResult = struct {
21582210 term: process.Child.Term,
21592211 stdout: ?[]const u8,
lib/compiler/objdump.zig+17-16
......@@ -1653,10 +1653,10 @@ const coff = struct {
16531653
16541654 fn dumpFlags(w: *Io.Writer, comptime fmt: []const u8, comptime T: type, flags: *const T, cols: u32) !void {
16551655 const s = @typeInfo(T).@"struct";
1656 inline for (s.fields) |flag_field| {
1657 if (flag_field.type == bool and @field(flags, flag_field.name)) {
1656 inline for (s.field_names, s.field_types) |field_name, field_type| {
1657 if (field_type == bool and @field(flags, field_name)) {
16581658 try w.splatByteAll(' ', cols);
1659 try w.print(fmt, .{flag_field.name});
1659 try w.print(fmt, .{field_name});
16601660 }
16611661 }
16621662 }
......@@ -1693,25 +1693,26 @@ const coff = struct {
16931693 header: *const T,
16941694 Custom: type,
16951695 ) !void {
1696 inline for (@typeInfo(T).@"struct".fields) |field| {
1697 const val = &@field(header, field.name);
1698 if (@hasDecl(Custom, field.name)) {
1699 try @field(Custom, field.name)(d, header);
1696 const s = @typeInfo(T).@"struct";
1697 inline for (s.field_names, s.field_types) |field_name, field_type| {
1698 const val = &@field(header, field_name);
1699 if (@hasDecl(Custom, field_name)) {
1700 try @field(Custom, field_name)(d, header);
17001701 } else {
1701 switch (@typeInfo(field.type)) {
1702 switch (@typeInfo(field_type)) {
17021703 .int => try d.w.print("{f} {s}\n", .{ fmtIntField(d, val.*, .{
1703 .kind = comptime fieldKind(field.name),
1704 .kind = comptime fieldKind(field_name),
17041705 .width = .{ .explicit = 16 },
1705 }), field.name }),
1706 .@"enum" => try d.w.print("{x: >16} {s} ({t})\n", .{ val.*, field.name, val.* }),
1707 .@"struct" => |s| {
1708 switch (s.layout) {
1706 }), field_name }),
1707 .@"enum" => try d.w.print("{x: >16} {s} ({t})\n", .{ val.*, field_name, val.* }),
1708 .@"struct" => |s_field| {
1709 switch (s_field.layout) {
17091710 .auto,
17101711 .@"extern",
1711 => try dumpHeader(d, field.type, val, Custom),
1712 => try dumpHeader(d, field_type, val, Custom),
17121713 .@"packed" => {
1713 try d.w.print("{x: >16} {s}\n", .{ @as(s.backing_integer.?, @bitCast(val.*)), field.name });
1714 try dumpFlags(d.w, "| {s}\n", field.type, val, 15);
1714 try d.w.print("{x: >16} {s}\n", .{ @as(s_field.backing_integer.?, @bitCast(val.*)), field_name });
1715 try dumpFlags(d.w, "| {s}\n", field_type, val, 15);
17151716 },
17161717 }
17171718 },
src/codegen/x86_64/Emit.zig+2-1
......@@ -155,6 +155,7 @@ pub fn emitMir(emit: *Emit) Error!void {
155155 @enumFromInt(try elf_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, null))
156156 else if (emit.bin_file.cast(.elf2)) |elf| try elf.externSymbol(.{
157157 .name = extern_func.toSlice(&emit.lower.mir).?,
158 .lib_name = null,
158159 .type = .FUNC,
159160 }) else if (emit.bin_file.cast(.macho)) |macho_file|
160161 @enumFromInt(try macho_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, null))
......@@ -254,7 +255,7 @@ pub fn emitMir(emit: *Emit) Error!void {
254255 else => unreachable,
255256 }
256257 } else if (emit.bin_file.cast(.coff2)) |_| {
257 if (reloc.target.is_dll_import) switch (lowered_inst.encoding.mnemonic) {
258 if (target.is_dll_import) switch (lowered_inst.encoding.mnemonic) {
258259 .lea => try emit.encodeInst(try .new(.none, .mov, &.{
259260 lowered_inst.ops[0],
260261 .{ .mem = .initRip(.ptr, 0) },
src/link/Coff.zig+167-77
......@@ -94,6 +94,13 @@ pub const imp_prefix = "__imp_";
9494
9595const header_name_max_len = @typeInfo(@FieldType(std.coff.SectionHeader, "name")).array.len;
9696
97const Error = link.Error || error{MappedFileIo};
98const LoadInputError = Error ||
99 Io.File.SeekError ||
100 Io.File.Reader.SizeError ||
101 Io.Reader.Error ||
102 MappedFile.Error;
103
97104/// This is the start of a Portable Executable (PE) file.
98105/// It starts with a MS-DOS header followed by a MS-DOS stub program.
99106/// This data does not change so we include it as follows in all binaries.
......@@ -484,7 +491,7 @@ pub const Member = struct {
484491 longnames,
485492 _,
486493
487 const known_count = @typeInfo(Index).@"enum".fields.len;
494 const known_count = @typeInfo(Index).@"enum".field_names.len;
488495
489496 pub fn get(member_index: Member.Index, coff: *Coff) *Member {
490497 return &coff.members.items[@intFromEnum(member_index)];
......@@ -2855,7 +2862,7 @@ pub fn getNavVAddr(
28552862 pt: Zcu.PerThread,
28562863 nav: InternPool.Nav.Index,
28572864 reloc_info: link.File.RelocInfo,
2858) !u64 {
2865) link.Error!u64 {
28592866 return coff.getVAddr(reloc_info, try coff.navSymbol(pt.zcu, nav));
28602867}
28612868
......@@ -2863,11 +2870,11 @@ pub fn getUavVAddr(
28632870 coff: *Coff,
28642871 uav: InternPool.Index,
28652872 reloc_info: link.File.RelocInfo,
2866) !u64 {
2873) link.Error!u64 {
28672874 return coff.getVAddr(reloc_info, try coff.uavSymbol(uav));
28682875}
28692876
2870pub fn getVAddr(coff: *Coff, reloc_info: link.File.RelocInfo, target_si: Symbol.Index) !u64 {
2877pub fn getVAddr(coff: *Coff, reloc_info: link.File.RelocInfo, target_si: Symbol.Index) link.Error!u64 {
28712878 try coff.addReloc(
28722879 @enumFromInt(@intFromEnum(reloc_info.parent.atom_index)),
28732880 reloc_info.offset,
......@@ -3524,19 +3531,13 @@ fn objectSectionMapIndex(
35243531 const parent_alignment = parent_ni.alignment(&coff.mf);
35253532 if (alignment.compare(.gt, parent_alignment)) {
35263533 log.debug("realignParent({s}, {d}) {d}->{d}", .{ name.toSlice(coff), parent_ni, parent_alignment, alignment });
3527 parent_ni.realign(&coff.mf, gpa, alignment, true) catch |err| switch (err) {
3528 error.Unimplemented => unreachable,
3529 else => |e| return e,
3530 };
3534 try parent_ni.realign(&coff.mf, gpa, alignment, true);
35313535 }
35323536
35333537 const old_alignment = sym.ni.alignment(&coff.mf);
35343538 if (alignment.compare(.gt, old_alignment)) {
35353539 log.debug("realignObject({s}) {d}->{d}", .{ name.toSlice(coff), old_alignment, alignment });
3536 sym.ni.realign(&coff.mf, gpa, alignment, true) catch |err| switch (err) {
3537 error.Unimplemented => unreachable,
3538 else => |e| return e,
3539 };
3540 try sym.ni.realign(&coff.mf, gpa, alignment, true);
35403541 }
35413542
35423543 try coff.verifyParentSectionAttributes(
......@@ -3561,7 +3562,6 @@ fn verifyParentSectionAttributes(
35613562) !void {
35623563 if (parent_attrs == child_attrs) return;
35633564
3564 const fields = std.meta.fields(ObjectSectionAttributes);
35653565 const BackingT = @typeInfo(ObjectSectionAttributes).@"struct".backing_integer.?;
35663566 const num_notes = @popCount(@as(BackingT, @bitCast(parent_attrs)) ^ @as(BackingT, @bitCast(child_attrs)));
35673567 var err = try coff.base.comp.link_diags.addErrorWithNotes(num_notes);
......@@ -3571,30 +3571,67 @@ fn verifyParentSectionAttributes(
35713571 parent_name.toSlice(coff),
35723572 });
35733573
3574 inline for (fields) |field| {
3575 if (@field(child_attrs, field.name) != @field(parent_attrs, field.name)) {
3574 inline for (comptime std.meta.fieldNames(ObjectSectionAttributes)) |field| {
3575 if (@field(child_attrs, field) != @field(parent_attrs, field)) {
35763576 err.addNote("flags.{s} was {d} in {s}, but {d} in {s}", .{
3577 field.name,
3578 @intFromBool(@field(child_attrs, field.name)),
3577 field,
3578 @intFromBool(@field(child_attrs, field)),
35793579 child_name.toSlice(coff),
3580 @intFromBool(@field(parent_attrs, field.name)),
3580 @intFromBool(@field(parent_attrs, field)),
35813581 parent_name.toSlice(coff),
35823582 });
35833583 }
35843584 }
35853585
3586 return error.LinkFailure;
3586 return error.AlreadyReported;
35873587}
35883588
3589const RelocAddend = union(enum) {
3590 known: i64,
3591 /// Relocs tables in input objects don't include the addend.
3592 /// The value needs to be recovered from the reloc location.
3593 pending: void,
3594};
3595
35893596pub fn addReloc(
35903597 coff: *Coff,
35913598 loc_si: Symbol.Index,
35923599 offset: u64,
35933600 target_si: Symbol.Index,
3594 addend: union(enum) {
3595 known: i64,
3596 pending: void,
3597 },
3601 addend: RelocAddend,
3602 @"type": Reloc.Type,
3603) link.Error!void {
3604 const diags = &coff.base.comp.link_diags;
3605 try coff.ensureUnusedRelocCapacity(loc_si, 1);
3606 coff.addRelocAssumeCapacity(loc_si, offset, target_si, addend, @"type") catch |err| switch (err) {
3607 error.MappedFileIo => return diags.fail(
3608 "failed to write output file: {t}",
3609 .{coff.mf.io_err.?},
3610 ),
3611 else => |e| return e,
3612 };
3613}
3614
3615fn ensureUnusedRelocCapacity(coff: *Coff, loc_si: Symbol.Index, len: usize) !void {
3616 const gpa = coff.base.comp.gpa;
3617 try coff.relocs.ensureUnusedCapacity(gpa, len);
3618 if (isImage(coff)) return;
3619 switch (loc_si.get(coff).section_number) {
3620 .UNDEFINED, .ABSOLUTE, .DEBUG => {},
3621 else => |loc_sn| {
3622 const section = loc_sn.section(coff);
3623 if (section.relocation_table_ni == .none)
3624 try coff.nodes.ensureUnusedCapacity(gpa, 1);
3625 },
3626 }
3627}
3628
3629fn addRelocAssumeCapacity(
3630 coff: *Coff,
3631 loc_si: Symbol.Index,
3632 offset: u64,
3633 target_si: Symbol.Index,
3634 addend: RelocAddend,
35983635 @"type": Reloc.Type,
35993636) !void {
36003637 const gpa = coff.base.comp.gpa;
......@@ -3612,8 +3649,6 @@ pub fn addReloc(
36123649 ri,
36133650 });
36143651
3615 try coff.relocs.ensureUnusedCapacity(gpa, 1);
3616
36173652 const sri: Section.RelocationIndex = if (isImage(coff))
36183653 .none
36193654 else switch (loc_si.get(coff).section_number) {
......@@ -3638,13 +3673,16 @@ pub fn addReloc(
36383673 const new_num_relocations = old_num_relocations + 1;
36393674 const new_size = new_num_relocations * std.coff.Relocation.sizeOf();
36403675 if (section.relocation_table_ni == .none) {
3641 try coff.nodes.ensureUnusedCapacity(gpa, 1);
3642 section.relocation_table_ni = try coff.mf.addLastChildNode(gpa, coff.sectionParent(), .{
3643 .size = new_size,
3644 .alignment = .@"2",
3645 .moved = true,
3646 .resized = true,
3647 });
3676 section.relocation_table_ni = try coff.mf.addLastChildNode(
3677 gpa,
3678 coff.sectionParent(),
3679 .{
3680 .size = new_size,
3681 .alignment = .@"2",
3682 .moved = true,
3683 .resized = true,
3684 },
3685 );
36483686 coff.nodes.appendAssumeCapacity(.{ .relocation_table = loc_sn });
36493687 } else {
36503688 try section.relocation_table_ni.resize(&coff.mf, gpa, new_size);
......@@ -3687,8 +3725,60 @@ pub fn addReloc(
36873725 target.target_relocs = ri;
36883726}
36893727
3690pub fn loadInput(coff: *Coff, input: link.Input) (Io.File.Reader.SizeError ||
3691 Io.File.Reader.Error || MappedFile.Error || error{ WriteFailed, EndOfStream, BadMagic, LinkFailure })!void {
3728// pub fn loadInput(coff: *Coff, input: link.Input) link.Error!void {
3729// const diags = &coff.base.comp.link_diags;
3730// return coff.loadInputInner(input) catch |err| switch (err) {
3731// else => |e| return e,
3732// error.MappedFileIo => return diags.fail(
3733// "failed to write output file: {t}",
3734// .{coff.mf.io_err.?},
3735// ),
3736// };
3737// }
3738
3739fn failLoadInput(
3740 coff: *Coff,
3741 err: LoadInputError,
3742 fr: *Io.File.Reader,
3743 path: std.Build.Cache.Path,
3744) link.Error {
3745 const diags = &coff.base.comp.link_diags;
3746 switch (err) {
3747 else => |e| return e,
3748 error.MappedFileIo => return diags.fail(
3749 "failed to write output file: {t}",
3750 .{coff.mf.io_err.?},
3751 ),
3752 error.EndOfStream => return diags.failParse(
3753 path,
3754 "unexpected eof",
3755 .{},
3756 ),
3757 error.AccessDenied,
3758 error.Unexpected,
3759 error.Unseekable,
3760 => |e| return diags.fail(
3761 "failed to read \"{f}\": {t}",
3762 .{ path.fmtEscapeString(), e },
3763 ),
3764 error.PermissionDenied,
3765 error.SystemResources,
3766 error.Streaming,
3767 => |e| return diags.fail(
3768 "failed to stat \"{f}\": {t}",
3769 .{ path.fmtEscapeString(), e },
3770 ),
3771 error.ReadFailed => switch (fr.err.?) {
3772 error.Canceled => |e| return e,
3773 else => |e| return diags.fail(
3774 "failed to read \"{f}\": {t}",
3775 .{ path.fmtEscapeString(), e },
3776 ),
3777 },
3778 }
3779}
3780
3781pub fn loadInput(coff: *Coff, input: link.Input) link.Error!void {
36923782 const comp = coff.base.comp;
36933783 const io = comp.io;
36943784
......@@ -3703,32 +3793,24 @@ pub fn loadInput(coff: *Coff, input: link.Input) (Io.File.Reader.SizeError ||
37033793 var fr = object.file.reader(io, &buf);
37043794 coff.loadObject(object.path, null, &fr, .{
37053795 .offset = fr.logicalPos(),
3706 .size = try fr.getSize(),
3707 }) catch |err| switch (err) {
3708 error.ReadFailed => return fr.err.?,
3709 else => |e| return e,
3710 };
3796 .size = fr.getSize() catch |err|
3797 return coff.failLoadInput(err, &fr, object.path),
3798 }) catch |err| return coff.failLoadInput(err, &fr, object.path);
37113799 },
37123800 .archive => |archive| {
37133801 var fr = archive.file.reader(io, &buf);
3714 coff.loadArchive(archive.path, &fr) catch |err| switch (err) {
3715 error.ReadFailed => return fr.err.?,
3716 else => |e| return e,
3717 };
3802 coff.loadArchive(archive.path, &fr) catch |err|
3803 return coff.failLoadInput(err, &fr, archive.path);
37183804 },
37193805 .res => |res| {
37203806 var fr = res.file.reader(io, &buf);
3721 coff.loadRes(res.path, &fr) catch |err| switch (err) {
3722 error.ReadFailed => return fr.err.?,
3723 else => |e| return e,
3724 };
3807 coff.loadRes(res.path, &fr) catch |err|
3808 return coff.failLoadInput(err, &fr, res.path);
37253809 },
37263810 .dso => |dso| {
37273811 var fr = dso.file.reader(io, &buf);
3728 coff.loadDll(dso.path, &fr) catch |err| switch (err) {
3729 error.ReadFailed => return fr.err.?,
3730 else => |e| return e,
3731 };
3812 coff.loadDll(dso.path, &fr) catch |err|
3813 return coff.failLoadInput(err, &fr, dso.path);
37323814 },
37333815 .dso_exact => unreachable,
37343816 }
......@@ -3771,7 +3853,7 @@ fn loadObject(
37713853 member_name: ?[]const u8,
37723854 fr: *Io.File.Reader,
37733855 fl: MappedFile.Node.FileLocation,
3774) !void {
3856) LoadInputError!void {
37753857 const comp = coff.base.comp;
37763858 const gpa = comp.gpa;
37773859 const diags = &comp.link_diags;
......@@ -3955,14 +4037,18 @@ fn loadObject(
39554037 try member.initHeader(coff, path_str, header.time_date_stamp);
39564038
39574039 {
3958 // TODO: This should be deferred to an idle task
4040 // TODO: This should be deferred to an idle task (but resize it here!)
39594041 var nw: MappedFile.Node.Writer = undefined;
39604042 member.content_ni.writer(&coff.mf, gpa, &nw);
39614043 defer nw.deinit();
39624044
39634045 try fr.seekTo(fl.offset);
3964 if (try nw.interface.sendFileAll(fr, .limited64(fl.size)) != fl.size)
3965 return error.EndOfStream;
4046 const written = nw.interface.sendFileAll(fr, .limited64(fl.size)) catch |err| switch (err) {
4047 error.WriteFailed => return nw.err.?,
4048 else => |e| return e,
4049 };
4050
4051 if (written != fl.size) return error.EndOfStream;
39664052 }
39674053
39684054 break :mi mi;
......@@ -4816,7 +4902,7 @@ fn failMultipleDefinitions(
48164902 size: struct { a: u64, b: u64 },
48174903 crc: struct { a: u32, b: u32 },
48184904 },
4819) error{ LinkFailure, OutOfMemory } {
4905) error{ AlreadyReported, OutOfMemory } {
48204906 const num_notes: usize = 2 + @as(usize, @intFromBool(comdat_reason != .none));
48214907 var err = try coff.base.comp.link_diags.addErrorWithNotes(num_notes);
48224908 try err.addMsg("multiple definitions of '{s}'", .{name.toSlice(coff)});
......@@ -4849,7 +4935,7 @@ fn failMultipleDefinitions(
48494935 ),
48504936 }
48514937
4852 return error.LinkFailure;
4938 return error.AlreadyReported;
48534939}
48544940
48554941const ArchiveMemberHeader = struct {
......@@ -4889,7 +4975,7 @@ fn parseArchiveMemberHeaderInner(
48894975 };
48904976}
48914977
4892fn loadArchive(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) !void {
4978fn loadArchive(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) LoadInputError!void {
48934979 const comp = coff.base.comp;
48944980 const gpa = comp.gpa;
48954981 const diags = &comp.link_diags;
......@@ -5164,7 +5250,7 @@ fn loadArchive(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) !vo
51645250 }
51655251}
51665252
5167fn loadRes(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) !void {
5253fn loadRes(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) LoadInputError!void {
51685254 const comp = coff.base.comp;
51695255 const gpa = comp.gpa;
51705256 const diags = &comp.link_diags;
......@@ -5177,7 +5263,7 @@ fn loadRes(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) !void {
51775263 _ = r;
51785264}
51795265
5180fn loadDll(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) !void {
5266fn loadDll(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) LoadInputError!void {
51815267 const comp = coff.base.comp;
51825268 const gpa = comp.gpa;
51835269 const diags = &comp.link_diags;
......@@ -5241,7 +5327,6 @@ pub fn prelink(coff: *Coff, prog_node: std.Progress.Node) link.Error!void {
52415327 errdefer archive.file.close(comp.io);
52425328
52435329 coff.loadInput(.{ .archive = archive }) catch |err| switch (err) {
5244 error.LinkFailure => return,
52455330 else => |e| return comp.link_diags.failParse(
52465331 lib.ioi.path(coff),
52475332 "error loading /DEFAULTLIB library '{s}': {t}",
......@@ -5265,10 +5350,14 @@ pub fn prelink(coff: *Coff, prog_node: std.Progress.Node) link.Error!void {
52655350 coff.exports_complete = true;
52665351}
52675352
5268pub fn updateNav(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {
5353pub fn updateNav(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) link.Error!void {
52695354 coff.updateNavInner(pt, nav_index) catch |err| switch (err) {
5355 error.MappedFileIo => return coff.base.cgFail(
5356 nav_index,
5357 "linker failed to update variable: {t}",
5358 .{coff.mf.io_err.?},
5359 ),
52705360 else => |e| return e,
5271 error.MappedFileIo => return coff.base.cgFail(nav_index, "linker failed to update variable: {t}", .{coff.mf.io_err.?}),
52725361 };
52735362}
52745363fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {
......@@ -5351,7 +5440,7 @@ pub fn lowerUav(
53515440 pt: Zcu.PerThread,
53525441 uav_val: InternPool.Index,
53535442 uav_align: InternPool.Alignment,
5354) !link.File.SymbolId {
5443) link.Error!link.File.SymbolId {
53555444 const zcu = pt.zcu;
53565445 const gpa = zcu.gpa;
53575446
......@@ -5380,7 +5469,7 @@ pub fn updateFunc(
53805469 pt: Zcu.PerThread,
53815470 func_index: InternPool.Index,
53825471 mir: *const codegen.AnyMir,
5383) !void {
5472) link.Error!void {
53845473 coff.updateFuncInner(pt, func_index, mir) catch |err| switch (err) {
53855474 else => |e| return e,
53865475 error.MappedFileIo => return coff.base.cgFail(
......@@ -5692,7 +5781,7 @@ fn reportUndefs(coff: *Coff, tid: Zcu.PerThread.Id) !void {
56925781 }
56935782 }
56945783
5695 return error.LinkFailure;
5784 return error.AlreadyReported;
56965785}
56975786
56985787pub fn flush(
......@@ -5700,7 +5789,7 @@ pub fn flush(
57005789 arena: std.mem.Allocator,
57015790 tid: Zcu.PerThread.Id,
57025791 prog_node: std.Progress.Node,
5703) !void {
5792) link.Error!void {
57045793 _ = arena;
57055794 _ = prog_node;
57065795 const comp = coff.base.comp;
......@@ -5723,13 +5812,10 @@ pub fn flush(
57235812 comp.gpa,
57245813 number_of_symbols * std.coff.Symbol.sizeOf(),
57255814 true,
5726 ) catch |err| switch (err) {
5727 error.OutOfMemory => return error.OutOfMemory,
5728 else => |e| return comp.link_diags.fail(
5729 "linker failed to compact symbol table: {t}",
5730 .{e},
5731 ),
5732 };
5815 ) catch |err| return comp.link_diags.fail(
5816 "linker failed to compact symbol table: {t}",
5817 .{err},
5818 );
57335819 }
57345820 while (try coff.idle(tid)) {}
57355821
......@@ -7220,10 +7306,14 @@ pub fn updateExports(
72207306 pt: Zcu.PerThread,
72217307 exported: Zcu.Exported,
72227308 export_indices: []const Zcu.Export.Index,
7223) !void {
7309) link.Error!void {
7310 const diags = &coff.base.comp.link_diags;
72247311 return coff.updateExportsInner(pt, exported, export_indices) catch |err| switch (err) {
7225 error.OutOfMemory => error.OutOfMemory,
7226 else => |e| coff.base.comp.link_diags.fail("updateExports failed {t}", .{e}) catch error.AnalysisFail,
7312 error.MappedFileIo => return diags.fail(
7313 "failed to write output file: {t}",
7314 .{coff.mf.io_err.?},
7315 ),
7316 else => |e| return e,
72277317 };
72287318}
72297319fn updateExportsInner(
src/link/Elf2.zig+4-4
......@@ -3787,7 +3787,7 @@ fn mapInputSection(elf: *Elf, opts: struct {
37873787 const new_alignment: std.mem.Alignment = .fromByteUnits(
37883788 std.math.ceilPowerOfTwoAssert(usize, @intCast(opts.addralign)),
37893789 );
3790 try existing_shndx.get(elf).ni.realign(&elf.mf, gpa, new_alignment);
3790 try existing_shndx.get(elf).ni.realign(&elf.mf, gpa, new_alignment, true);
37913791 }
37923792 // ...and update the shdr as needed.
37933793 switch (elf.shdrPtr(existing_shndx)) {
......@@ -3950,7 +3950,7 @@ fn uavMapIndex(
39503950 } else {
39513951 const node = uav_gop.value_ptr.lsi.index().ptr(elf).node;
39523952 if (resolved_align.toStdMem().order(node.alignment(&elf.mf)).compare(.gt)) {
3953 try node.realign(&elf.mf, gpa, resolved_align.toStdMem());
3953 try node.realign(&elf.mf, gpa, resolved_align.toStdMem(), true);
39543954 }
39553955 }
39563956 return umi;
......@@ -4679,7 +4679,7 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (LoadPars
46794679 // We have a copy relocation for this global, but the amount of space we
46804680 // reserved for it could be too small or underaligned!
46814681 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);
4682 try copied_global.node.realign(&elf.mf, gpa, gop.value_ptr.alignment, true);
46834683 const global_ptr = elf.globalByName(name).?;
46844684 switch (elf.symPtr(global_ptr.symtab_index)) {
46854685 inline else => |sym_ptr| elf.targetStore(&sym_ptr.size, @intCast(gop.value_ptr.size)),
......@@ -6762,7 +6762,7 @@ pub fn printNode(
67626762 elf.getNode(isi.node(elf).parent(&elf.mf)).section.name(elf).slice(elf),
67636763 });
67646764 },
6765 .copied_global => |name| try w.print("(copy:{s})", .{name}),
6765 .copied_global => |name| try w.print("(copy:{s})", .{name.slice(elf)}),
67666766 .nav => |nmi| {
67676767 const zcu = elf.base.comp.zcu.?;
67686768 const ip = &zcu.intern_pool;
src/link/MappedFile.zig+16-9
......@@ -385,13 +385,14 @@ pub const Node = extern struct {
385385 /// If the new size can't contain all the children, returns error.ShrinkImpossible.
386386 /// If `shift_next` is set, then the following node is shifted backwards into
387387 /// the free space as much as alignment allows.
388 /// Asserts that `size` is >= the end of the last child node.
388389 pub fn shrink(
389390 ni: Node.Index,
390391 mf: *MappedFile,
391392 gpa: std.mem.Allocator,
392393 size: u64,
393394 shift_next: bool,
394 ) !void {
395 ) Error!void {
395396 try mf.shrinkNode(gpa, ni, size, shift_next);
396397 var writers_it = mf.writers.first;
397398 while (writers_it) |writer_node| : (writers_it = writer_node.next) {
......@@ -572,10 +573,7 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {
572573 else => |next_ni| {
573574 const next_offset, _ = next_ni.location(mf).resolve(mf);
574575 if (new_end > next_offset)
575 mf.realignNode(gpa, next_ni, opts.add_node.alignment, false, false) catch |err| switch (err) {
576 error.Unimplemented => unreachable,
577 else => |e| return e,
578 };
576 try next_ni.realign(mf, gpa, opts.add_node.alignment, false);
579577 },
580578 }
581579 }
......@@ -724,13 +722,13 @@ fn shrinkNode(
724722 const old_offset, _ = node.location().resolve(mf);
725723
726724 // This would require unmapping first
727 if (ni == Node.Index.root) return error.Unimplemented;
725 assert(ni != Node.Index.root);
728726 defer if (std.debug.runtime_safety) mf.verify();
729727
730728 if (node.last != .none) {
731729 const last = node.last.get(mf);
732730 const last_offset, const last_size = last.location().resolve(mf);
733 if (last_offset + last_size > size) return error.ShrinkImpossible;
731 assert(last_offset + last_size > size);
734732 }
735733
736734 try mf.large.ensureUnusedCapacity(gpa, 4);
......@@ -757,7 +755,12 @@ fn shrinkNode(
757755 node.next.setLocationAssumeCapacity(mf, new_next_offset, next_size);
758756}
759757
760fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested_size: u64) (Allocator.Error || Io.Cancelable || IoError)!void {
758fn resizeNode(
759 mf: *MappedFile,
760 gpa: std.mem.Allocator,
761 ni: Node.Index,
762 requested_size: u64,
763) (Allocator.Error || Io.Cancelable || IoError)!void {
761764 mf.nodes_lock.assertUnlocked();
762765 const io = mf.io;
763766 const node = ni.get(mf);
......@@ -1271,7 +1274,11 @@ fn ensureTotalCapacityPreciseInner(mf: *MappedFile, new_capacity: usize) (Alloca
12711274 else => |e| return e,
12721275 }
12731276
1274 try mf.memory_map.write(io);
1277 mf.memory_map.write(io) catch |err| switch (err) {
1278 error.WouldBlock => return error.Unexpected, // file was not opened as non-blocking
1279 error.NotOpenForWriting => return error.Unexpected, // we definitely opened the file for writing
1280 else => |e| return e,
1281 };
12751282 unmap(mf);
12761283 }
12771284
test/src/Link.zig+1-1
......@@ -151,7 +151,7 @@ pub const Case = struct {
151151 const snapshot_update_path = run_step.captureStdOut(.{});
152152 update_step.addCopyFileToSource(snapshot_update_path, snapshot_sub_path);
153153 } else {
154 run_step.addCheck(.{ .snapshot = .{ .file = ctx.b.path(snapshot_sub_path) } });
154 run_step.addCheck(.{ .expect_stdout_snapshot = ctx.b.path(snapshot_sub_path) });
155155 }
156156
157157 ctx.step.dependOn(&run_step.step);