authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-05-31 06:13:47+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-06-01 10:26:01+01:00
log8fe1ec0cc9cfd0f3cf85b97889b4b9735e906926
tree0bd86634dd23d30464e0d75cd3e168945a169dda
parent748e7c5e39fcba3ed6b2b6e4cc4c01e1d442acbe
signaturelock-open Commit is signed but in an unrecognized format.

compiler: refactor backend error handling

All public codegen and linker APIs now use the following error set: Allocator.Error || Io.Cancelable || error{AlreadyReported} This is defined as `link.Error` and aliased as `codegen.Error`. The compiler "backend" (including both codegen and linker) has a fairly limited set of failure modes. Most of them are as follows: * Bad inline assembly (codegen) * Output file I/O error (link) * Symbol with no definition or multiple definitions (link) * Relocation error, e.g. overflow (link) * Unimplemented/unsupported feature (codegen/link) * `error.OutOfMemory` (codegen/link) * `error.Canceled` (codegen/link) The last two cases are special, because they are possible across most of the compiler codebase and have fixed code paths for handling---e.g. `error.OutOfMemory` almost always calls `Compilation.setAllocFailure`, and `error.Canceled` should typically propagate all the way up the call stack. However, all of the other cases should follow the same general pattern: the codegen/linker implementation should mark an error on `Compilation` somehow (either through `link_diags` or `failed_codegen`), and return `error.AlreadyReported`. This error code indicates that an operation failed, but that the caller does not need to take action to recover, because the failure has already been recorded in a way which will be expressed to the user. For instance, the codegen error set used to contain `error.Overflow`, but this case should have already been reported to the user, because implementation-agnostic code cannot know how best to express the failure to the user. The `error.AlreadyReported` error code encompasses what was previously represented by multiple errors, including `error.CodegenFail`, `error.LinkFailure`, and `error.AnalysisFail`. It is not necessary to differentiate these cases. (Not to be confused with the usage of `error.AnalysisFail` in the compiler *frontend*, i.e. `Sema`, which is unchanged by this diff.) Because the backend error set is now very small, it is easy to exhaustively `switch` on, and also many functions can be given concrete error sets. There are no longer different error sets for different operations. (As an exception, I have not tackled `link.File.open` in this diff, which has a big inferred error set where I think most errors are reported to the user with an `else => |e|` case.) I have also changed how `link.MappedFile`, our abstraction for handling the awkward "moving things around" aspect of incremental linking, does error handling. The public API of this abstraction now uses the following small error set: Allocator.Error || Io.Cancelable || error{MappedFileIo} The first two cases are self-explanatory. Then, `error.MappedFileIo` is a catch-all error code encompassing that an error was encountered when accessing the underlying `Io.File`. This error may have occurred when attempting to flush the file to disk, or to change its size, etc. In this case, the *specific* error---which was actually returned from the `Io.File` API---is available in the `MappedFile.io_err.?` field. Linker implementations which use `MappedFile` (currently `Elf2` and `Coff`) should eventually handle `error.MappedFileIo` by reporting an error in `Compilation.link_diags`, including that specific I/O error in the error message. The rationale here is essentially that error codes returned from functions exist for control flow purposes, and a linker implementation should not care about the distinction between file I/O error codes (e.g. `error.DiskQuota` vs `error.InputOutput`). The only reason it needs the concrete error is to expose it to the user. Therefore, by wrapping these failure modes under `error.MappedFileIo`, we keep the error set actually used by the linker implementation as small as possible, which encourages avoiding patterns like `else => |e| diags.fail(...)` (which is potentially dangerous since it may prevent `error.OutOfMemory` or `error.Canceled` from propagating correctly). It additionally helps linker implementations maintain more precise error messages---for instance, if `Elf2` encounters `error.NoSpaceLeft` writing to the output file, the error will now read "failed to write output file: NoSpaceLeft" instead of something more generic like "prelink failed: NoSpaceLeft". Finally, while working on these refactors, I was able to eliminate those pesky `src_loc: Zcu.LazySrcLoc` parameters from the codegen and link logic. These parameters did not make sense, because at this point in the compiler pipeline, we do not have precise source location information---so these parameters were always passed as just the location of the function declaration, or as some placeholder (`.unneeded` or the top of `lib/std/std.zig`) if there wasn't an appropriate function definition. The only logic which actually *uses* these source locations is codegen implementations' `fail` functions. Per my earlier list of failure modes, those functions are called in two main cases: * Bad inline assembly * Unimplemented/unsupported feature The first case should be moved to the compiler frontend (tracked by https://github.com/ziglang/zig/issues/10761), while the second case is essentially a compiler TODO so it is permissible for it to have imprecise error reporting. Therefore, codegen implementations' `fail` functions now just call `navSrcLoc` themselves when necessary, which (once we make improvements to inline assembly) will only happen when there is a deficiency in the codegen implementation. I was careful to make `Elf2` and `Coff` error reporting work well in this diff, by using no `else` case other than `else => |e| return e` when `switch`ing on errors and by always handling `error.MappedFileIo` by unwrapping `MappedFile.io_err.?`. I also added concrete error sets to almost every function in `Elf2`. (That was, um, actually why I started this diff, because it was annoying me that I wouldn't get as many compile errors at once...)

42 files changed, 973 insertions(+), 1126 deletions(-)

src/Compilation.zig+11-11
...@@ -3376,7 +3376,7 @@ fn flush(comp: *Compilation, arena: Allocator, tid: Zcu.PerThread.Id) (Io.Cancel...@@ -3376,7 +3376,7 @@ fn flush(comp: *Compilation, arena: Allocator, tid: Zcu.PerThread.Id) (Io.Cancel
3376 .fuzz = comp.config.any_fuzz,3376 .fuzz = comp.config.any_fuzz,
3377 .lto = comp.config.lto,3377 .lto = comp.config.lto,
3378 }) catch |err| switch (err) {3378 }) catch |err| switch (err) {
3379 error.LinkFailure => {}, // Already reported.3379 error.AlreadyReported => {},
3380 error.OutOfMemory => |e| return e,3380 error.OutOfMemory => |e| return e,
3381 };3381 };
3382 }3382 }
...@@ -3390,7 +3390,7 @@ fn flush(comp: *Compilation, arena: Allocator, tid: Zcu.PerThread.Id) (Io.Cancel...@@ -3390,7 +3390,7 @@ fn flush(comp: *Compilation, arena: Allocator, tid: Zcu.PerThread.Id) (Io.Cancel
3390 };3390 };
3391 // This is needed before reading the error flags.3391 // This is needed before reading the error flags.
3392 lf.flush(arena, tid, comp.link_prog_node) catch |err| switch (err) {3392 lf.flush(arena, tid, comp.link_prog_node) catch |err| switch (err) {
3393 error.LinkFailure => {}, // Already reported.3393 error.AlreadyReported => {},
3394 error.OutOfMemory, error.Canceled => |e| return e,3394 error.OutOfMemory, error.Canceled => |e| return e,
3395 };3395 };
3396 }3396 }
...@@ -5249,7 +5249,7 @@ fn workerUpdateCObject(...@@ -5249,7 +5249,7 @@ fn workerUpdateCObject(
5249 progress_node: std.Progress.Node,5249 progress_node: std.Progress.Node,
5250) void {5250) void {
5251 comp.updateCObject(c_object, progress_node) catch |err| switch (err) {5251 comp.updateCObject(c_object, progress_node) catch |err| switch (err) {
5252 error.AnalysisFail => return,5252 error.AlreadyReported => return,
5253 else => {5253 else => {
5254 comp.reportRetryableCObjectError(c_object, err) catch |oom| switch (oom) {5254 comp.reportRetryableCObjectError(c_object, err) catch |oom| switch (oom) {
5255 // Swallowing this error is OK because it's implied to be OOM when5255 // Swallowing this error is OK because it's implied to be OOM when
...@@ -5266,7 +5266,7 @@ fn workerUpdateWin32Resource(...@@ -5266,7 +5266,7 @@ fn workerUpdateWin32Resource(
5266 progress_node: std.Progress.Node,5266 progress_node: std.Progress.Node,
5267) void {5267) void {
5268 comp.updateWin32Resource(win32_resource, progress_node) catch |err| switch (err) {5268 comp.updateWin32Resource(win32_resource, progress_node) catch |err| switch (err) {
5269 error.AnalysisFail => return,5269 error.AlreadyReported => return,
5270 else => {5270 else => {
5271 comp.reportRetryableWin32ResourceError(win32_resource, err) catch |oom| switch (oom) {5271 comp.reportRetryableWin32ResourceError(win32_resource, err) catch |oom| switch (oom) {
5272 // Swallowing this error is OK because it's implied to be OOM when5272 // Swallowing this error is OK because it's implied to be OOM when
...@@ -5489,7 +5489,7 @@ fn reportRetryableCObjectError(comp: *Compilation, c_object: *CObject, err: anye...@@ -5489,7 +5489,7 @@ fn reportRetryableCObjectError(comp: *Compilation, c_object: *CObject, err: anye
5489 c_object.status = .failure_retryable;5489 c_object.status = .failure_retryable;
54905490
5491 switch (comp.failCObj(c_object, "{t}", .{err})) {5491 switch (comp.failCObj(c_object, "{t}", .{err})) {
5492 error.AnalysisFail => return,5492 error.AlreadyReported => return,
5493 else => |e| return e,5493 else => |e| return e,
5494 }5494 }
5495}5495}
...@@ -6852,7 +6852,7 @@ fn failCObj(...@@ -6852,7 +6852,7 @@ fn failCObj(
6852 c_object: *CObject,6852 c_object: *CObject,
6853 comptime format: []const u8,6853 comptime format: []const u8,
6854 args: anytype,6854 args: anytype,
6855) error{ OutOfMemory, AnalysisFail } {6855) error{ OutOfMemory, AlreadyReported } {
6856 @branchHint(.cold);6856 @branchHint(.cold);
6857 const diag_bundle = blk: {6857 const diag_bundle = blk: {
6858 const diag_bundle = try comp.gpa.create(CObject.Diag.Bundle);6858 const diag_bundle = try comp.gpa.create(CObject.Diag.Bundle);
...@@ -6876,7 +6876,7 @@ fn failCObjWithOwnedDiagBundle(...@@ -6876,7 +6876,7 @@ fn failCObjWithOwnedDiagBundle(
6876 comp: *Compilation,6876 comp: *Compilation,
6877 c_object: *CObject,6877 c_object: *CObject,
6878 diag_bundle: *CObject.Diag.Bundle,6878 diag_bundle: *CObject.Diag.Bundle,
6879) error{ OutOfMemory, AnalysisFail } {6879) error{ OutOfMemory, AlreadyReported } {
6880 @branchHint(.cold);6880 @branchHint(.cold);
6881 assert(diag_bundle.diags.len > 0);6881 assert(diag_bundle.diags.len > 0);
6882 {6882 {
...@@ -6890,10 +6890,10 @@ fn failCObjWithOwnedDiagBundle(...@@ -6890,10 +6890,10 @@ fn failCObjWithOwnedDiagBundle(
6890 comp.failed_c_objects.putAssumeCapacityNoClobber(c_object, diag_bundle);6890 comp.failed_c_objects.putAssumeCapacityNoClobber(c_object, diag_bundle);
6891 }6891 }
6892 c_object.status = .failure;6892 c_object.status = .failure;
6893 return error.AnalysisFail;6893 return error.AlreadyReported;
6894}6894}
68956895
6896fn failWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, comptime format: []const u8, args: anytype) error{ OutOfMemory, AnalysisFail } {6896fn failWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, comptime format: []const u8, args: anytype) error{ OutOfMemory, AlreadyReported } {
6897 @branchHint(.cold);6897 @branchHint(.cold);
6898 var bundle: ErrorBundle.Wip = undefined;6898 var bundle: ErrorBundle.Wip = undefined;
6899 try bundle.init(comp.gpa);6899 try bundle.init(comp.gpa);
...@@ -6920,7 +6920,7 @@ fn failWin32ResourceWithOwnedBundle(...@@ -6920,7 +6920,7 @@ fn failWin32ResourceWithOwnedBundle(
6920 comp: *Compilation,6920 comp: *Compilation,
6921 win32_resource: *Win32Resource,6921 win32_resource: *Win32Resource,
6922 err_bundle: ErrorBundle,6922 err_bundle: ErrorBundle,
6923) error{ OutOfMemory, AnalysisFail } {6923) error{ OutOfMemory, AlreadyReported } {
6924 @branchHint(.cold);6924 @branchHint(.cold);
6925 {6925 {
6926 const io = comp.io;6926 const io = comp.io;
...@@ -6929,7 +6929,7 @@ fn failWin32ResourceWithOwnedBundle(...@@ -6929,7 +6929,7 @@ fn failWin32ResourceWithOwnedBundle(
6929 try comp.failed_win32_resources.putNoClobber(comp.gpa, win32_resource, err_bundle);6929 try comp.failed_win32_resources.putNoClobber(comp.gpa, win32_resource, err_bundle);
6930 }6930 }
6931 win32_resource.status = .failure;6931 win32_resource.status = .failure;
6932 return error.AnalysisFail;6932 return error.AlreadyReported;
6933}6933}
69346934
6935pub const FileExt = enum {6935pub const FileExt = enum {
src/Zcu.zig+8-17
...@@ -3912,12 +3912,12 @@ pub fn getTarget(zcu: *const Zcu) *const Target {...@@ -3912,12 +3912,12 @@ pub fn getTarget(zcu: *const Zcu) *const Target {
3912pub fn handleUpdateExports(3912pub fn handleUpdateExports(
3913 zcu: *Zcu,3913 zcu: *Zcu,
3914 export_indices: []const Export.Index,3914 export_indices: []const Export.Index,
3915 result: link.File.UpdateExportsError!void,3915 result: link.Error!void,
3916) Allocator.Error!void {3916) (Allocator.Error || Io.Cancelable)!void {
3917 const gpa = zcu.gpa;3917 const gpa = zcu.gpa;
3918 result catch |err| switch (err) {3918 result catch |err| switch (err) {
3919 error.OutOfMemory => |e| return e,3919 else => |e| return e,
3920 error.AnalysisFail => {3920 error.AlreadyReported => {
3921 const export_idx = export_indices[0];3921 const export_idx = export_indices[0];
3922 const new_export = export_idx.ptr(zcu);3922 const new_export = export_idx.ptr(zcu);
3923 new_export.status = .failed_retryable;3923 new_export.status = .failed_retryable;
...@@ -4688,7 +4688,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)...@@ -4688,7 +4688,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)
46884688
4689pub const CodegenFailError = error{4689pub const CodegenFailError = error{
4690 /// Indicates the error message has been already stored at `Zcu.failed_codegen`.4690 /// Indicates the error message has been already stored at `Zcu.failed_codegen`.
4691 CodegenFail,4691 AlreadyReported,
4692 OutOfMemory,4692 OutOfMemory,
4693};4693};
46944694
...@@ -4713,16 +4713,7 @@ pub fn codegenFailMsg(zcu: *Zcu, nav_index: InternPool.Nav.Index, msg: *ErrorMsg...@@ -4713,16 +4713,7 @@ pub fn codegenFailMsg(zcu: *Zcu, nav_index: InternPool.Nav.Index, msg: *ErrorMsg
4713 errdefer msg.deinit(gpa);4713 errdefer msg.deinit(gpa);
4714 try zcu.failed_codegen.putNoClobber(gpa, nav_index, msg);4714 try zcu.failed_codegen.putNoClobber(gpa, nav_index, msg);
4715 }4715 }
4716 return error.CodegenFail;4716 return error.AlreadyReported;
4717}
4718
4719/// Asserts that `zcu.failed_codegen` contains the key `nav`, with the necessary lock held.
4720pub fn assertCodegenFailed(zcu: *Zcu, nav: InternPool.Nav.Index) void {
4721 const comp = zcu.comp;
4722 const io = comp.io;
4723 comp.mutex.lockUncancelable(io);
4724 defer comp.mutex.unlock(io);
4725 assert(zcu.failed_codegen.contains(nav));
4726}4717}
47274718
4728pub fn codegenFailType(4719pub fn codegenFailType(
...@@ -4735,7 +4726,7 @@ pub fn codegenFailType(...@@ -4735,7 +4726,7 @@ pub fn codegenFailType(
4735 try zcu.failed_types.ensureUnusedCapacity(gpa, 1);4726 try zcu.failed_types.ensureUnusedCapacity(gpa, 1);
4736 const msg = try Zcu.ErrorMsg.create(gpa, zcu.typeSrcLoc(ty_index), format, args);4727 const msg = try Zcu.ErrorMsg.create(gpa, zcu.typeSrcLoc(ty_index), format, args);
4737 zcu.failed_types.putAssumeCapacityNoClobber(ty_index, msg);4728 zcu.failed_types.putAssumeCapacityNoClobber(ty_index, msg);
4738 return error.CodegenFail;4729 return error.AlreadyReported;
4739}4730}
47404731
4741pub fn codegenFailTypeMsg(zcu: *Zcu, ty_index: InternPool.Index, msg: *ErrorMsg) CodegenFailError {4732pub fn codegenFailTypeMsg(zcu: *Zcu, ty_index: InternPool.Index, msg: *ErrorMsg) CodegenFailError {
...@@ -4745,7 +4736,7 @@ pub fn codegenFailTypeMsg(zcu: *Zcu, ty_index: InternPool.Index, msg: *ErrorMsg)...@@ -4745,7 +4736,7 @@ pub fn codegenFailTypeMsg(zcu: *Zcu, ty_index: InternPool.Index, msg: *ErrorMsg)
4745 try zcu.failed_types.ensureUnusedCapacity(gpa, 1);4736 try zcu.failed_types.ensureUnusedCapacity(gpa, 1);
4746 }4737 }
4747 zcu.failed_types.putAssumeCapacityNoClobber(ty_index, msg);4738 zcu.failed_types.putAssumeCapacityNoClobber(ty_index, msg);
4748 return error.CodegenFail;4739 return error.AlreadyReported;
4749}4740}
47504741
4751/// Asserts that `zcu.multi_module_err != null`.4742/// Asserts that `zcu.multi_module_err != null`.
src/Zcu/PerThread.zig+5-12
...@@ -3700,7 +3700,7 @@ fn processExportsInner(...@@ -3700,7 +3700,7 @@ fn processExportsInner(
3700 exported: Zcu.Exported,3700 exported: Zcu.Exported,
3701 export_indices: []const Zcu.Export.Index,3701 export_indices: []const Zcu.Export.Index,
3702 skip_linker_work: bool,3702 skip_linker_work: bool,
3703) error{OutOfMemory}!void {3703) error{ OutOfMemory, Canceled }!void {
3704 const zcu = pt.zcu;3704 const zcu = pt.zcu;
3705 const gpa = zcu.gpa;3705 const gpa = zcu.gpa;
3706 const ip = &zcu.intern_pool;3706 const ip = &zcu.intern_pool;
...@@ -4533,7 +4533,7 @@ pub fn runCodegen(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) Ru...@@ -4533,7 +4533,7 @@ pub fn runCodegen(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) Ru
4533 return codegen_result catch |err| {4533 return codegen_result catch |err| {
4534 switch (err) {4534 switch (err) {
4535 error.OutOfMemory => comp.setAllocFailure(),4535 error.OutOfMemory => comp.setAllocFailure(),
4536 error.CodegenFail => zcu.assertCodegenFailed(zcu.funcInfo(func_index).owner_nav),4536 error.AlreadyReported => {},
4537 error.NoLinkFile => assert(comp.bin_file == null),4537 error.NoLinkFile => assert(comp.bin_file == null),
4538 error.BackendDoesNotProduceMir => switch (target_util.zigBackend(4538 error.BackendDoesNotProduceMir => switch (target_util.zigBackend(
4539 &zcu.root_mod.resolved_target.result,4539 &zcu.root_mod.resolved_target.result,
...@@ -4552,7 +4552,7 @@ pub fn runCodegen(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) Ru...@@ -4552,7 +4552,7 @@ pub fn runCodegen(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) Ru
4552fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) error{4552fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) error{
4553 OutOfMemory,4553 OutOfMemory,
4554 Canceled,4554 Canceled,
4555 CodegenFail,4555 AlreadyReported,
4556 NoLinkFile,4556 NoLinkFile,
4557 BackendDoesNotProduceMir,4557 BackendDoesNotProduceMir,
4558}!codegen.AnyMir {4558}!codegen.AnyMir {
...@@ -4628,19 +4628,12 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e...@@ -4628,19 +4628,12 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e
4628 switch (err) {4628 switch (err) {
4629 error.OutOfMemory => comp.link_diags.setAllocFailure(),4629 error.OutOfMemory => comp.link_diags.setAllocFailure(),
4630 }4630 }
4631 return error.CodegenFail;4631 return error.AlreadyReported;
4632 };4632 };
4633 return error.BackendDoesNotProduceMir;4633 return error.BackendDoesNotProduceMir;
4634 }4634 }
46354635
4636 return codegen.generateFunction(lf, pt, zcu.navSrcLoc(nav), func_index, air, &liveness) catch |err| switch (err) {4636 return codegen.generateFunction(lf, pt, func_index, air, &liveness);
4637 error.OutOfMemory,
4638 error.CodegenFail,
4639 => |e| return e,
4640 error.Overflow,
4641 error.RelocationNotByteAligned,
4642 => return zcu.codegenFail(nav, "unable to codegen: {s}", .{@errorName(err)}),
4643 };
4644}4637}
46454638
4646fn printVerboseAir(4639fn printVerboseAir(
src/codegen.zig+99-154
...@@ -24,10 +24,7 @@ const dev = @import("dev.zig");...@@ -24,10 +24,7 @@ const dev = @import("dev.zig");
2424
25pub const aarch64 = @import("codegen/aarch64.zig");25pub const aarch64 = @import("codegen/aarch64.zig");
2626
27pub const CodeGenError = GenerateSymbolError || error{27pub const Error = link.Error;
28 /// Indicates the error is already stored in Zcu `failed_codegen`.
29 CodegenFail,
30};
3128
32fn devFeatureForBackend(backend: std.lang.CompilerBackend) dev.Feature {29fn devFeatureForBackend(backend: std.lang.CompilerBackend) dev.Feature {
33 return switch (backend) {30 return switch (backend) {
...@@ -141,11 +138,10 @@ pub const AnyMir = union {...@@ -141,11 +138,10 @@ pub const AnyMir = union {
141pub fn generateFunction(138pub fn generateFunction(
142 lf: *link.File,139 lf: *link.File,
143 pt: Zcu.PerThread,140 pt: Zcu.PerThread,
144 src_loc: Zcu.LazySrcLoc,
145 func_index: InternPool.Index,141 func_index: InternPool.Index,
146 air: *const Air,142 air: *const Air,
147 liveness: *const ?Air.Liveness,143 liveness: *const ?Air.Liveness,
148) CodeGenError!AnyMir {144) Error!AnyMir {
149 const zcu = pt.zcu;145 const zcu = pt.zcu;
150 const func = zcu.funcInfo(func_index);146 const func = zcu.funcInfo(func_index);
151 const target = &zcu.navFileScope(func.owner_nav).mod.?.resolved_target.result;147 const target = &zcu.navFileScope(func.owner_nav).mod.?.resolved_target.result;
...@@ -160,7 +156,7 @@ pub fn generateFunction(...@@ -160,7 +156,7 @@ pub fn generateFunction(
160 => |backend| {156 => |backend| {
161 dev.check(devFeatureForBackend(backend));157 dev.check(devFeatureForBackend(backend));
162 const CodeGen = importBackend(backend);158 const CodeGen = importBackend(backend);
163 const mir = try CodeGen.generate(lf, pt, src_loc, func_index, air, liveness);159 const mir = try CodeGen.generate(lf, pt, func_index, air, liveness);
164 return @unionInit(AnyMir, AnyMir.tag(backend), mir);160 return @unionInit(AnyMir, AnyMir.tag(backend), mir);
165 },161 },
166 }162 }
...@@ -176,13 +172,12 @@ pub fn generateFunction(...@@ -176,13 +172,12 @@ pub fn generateFunction(
176pub fn emitFunction(172pub fn emitFunction(
177 lf: *link.File,173 lf: *link.File,
178 pt: Zcu.PerThread,174 pt: Zcu.PerThread,
179 src_loc: Zcu.LazySrcLoc,
180 func_index: InternPool.Index,175 func_index: InternPool.Index,
181 atom_id: link.File.AtomId,176 atom_id: link.File.AtomId,
182 any_mir: *const AnyMir,177 any_mir: *const AnyMir,
183 w: *std.Io.Writer,178 w: *std.Io.Writer,
184 debug_output: link.File.DebugInfoOutput,179 debug_output: link.File.DebugInfoOutput,
185) (CodeGenError || std.Io.Writer.Error)!void {180) (Error || std.Io.Writer.Error)!void {
186 const zcu = pt.zcu;181 const zcu = pt.zcu;
187 const func = zcu.funcInfo(func_index);182 const func = zcu.funcInfo(func_index);
188 const target = &zcu.navFileScope(func.owner_nav).mod.?.resolved_target.result;183 const target = &zcu.navFileScope(func.owner_nav).mod.?.resolved_target.result;
...@@ -201,7 +196,7 @@ pub fn emitFunction(...@@ -201,7 +196,7 @@ pub fn emitFunction(
201 => |backend| {196 => |backend| {
202 dev.check(devFeatureForBackend(backend));197 dev.check(devFeatureForBackend(backend));
203 const mir = &@field(any_mir, AnyMir.tag(backend));198 const mir = &@field(any_mir, AnyMir.tag(backend));
204 return mir.emit(lf, pt, src_loc, func_index, atom_id, w, debug_output);199 return mir.emit(lf, pt, func_index, atom_id, w, debug_output);
205 },200 },
206 }201 }
207}202}
...@@ -209,12 +204,11 @@ pub fn emitFunction(...@@ -209,12 +204,11 @@ pub fn emitFunction(
209pub fn generateLazyFunction(204pub fn generateLazyFunction(
210 lf: *link.File,205 lf: *link.File,
211 pt: Zcu.PerThread,206 pt: Zcu.PerThread,
212 src_loc: Zcu.LazySrcLoc,
213 lazy_sym: link.File.LazySymbol,207 lazy_sym: link.File.LazySymbol,
214 atom_id: link.File.AtomId,208 atom_id: link.File.AtomId,
215 w: *std.Io.Writer,209 w: *std.Io.Writer,
216 debug_output: link.File.DebugInfoOutput,210 debug_output: link.File.DebugInfoOutput,
217) (CodeGenError || std.Io.Writer.Error)!void {211) (Error || std.Io.Writer.Error)!void {
218 const zcu = pt.zcu;212 const zcu = pt.zcu;
219 const target = if (Type.fromInterned(lazy_sym.ty).typeDeclInstAllowGeneratedTag(zcu)) |inst_index|213 const target = if (Type.fromInterned(lazy_sym.ty).typeDeclInstAllowGeneratedTag(zcu)) |inst_index|
220 &zcu.fileByIndex(inst_index.resolveFile(&zcu.intern_pool)).mod.?.resolved_target.result214 &zcu.fileByIndex(inst_index.resolveFile(&zcu.intern_pool)).mod.?.resolved_target.result
...@@ -224,7 +218,7 @@ pub fn generateLazyFunction(...@@ -224,7 +218,7 @@ pub fn generateLazyFunction(
224 else => unreachable,218 else => unreachable,
225 inline .stage2_riscv64, .stage2_x86_64 => |backend| {219 inline .stage2_riscv64, .stage2_x86_64 => |backend| {
226 dev.check(devFeatureForBackend(backend));220 dev.check(devFeatureForBackend(backend));
227 return importBackend(backend).generateLazy(lf, pt, src_loc, lazy_sym, atom_id, w, debug_output);221 return importBackend(backend).generateLazy(lf, pt, lazy_sym, atom_id, w, debug_output);
228 },222 },
229 }223 }
230}224}
...@@ -232,14 +226,13 @@ pub fn generateLazyFunction(...@@ -232,14 +226,13 @@ pub fn generateLazyFunction(
232pub fn generateLazySymbol(226pub fn generateLazySymbol(
233 bin_file: *link.File,227 bin_file: *link.File,
234 pt: Zcu.PerThread,228 pt: Zcu.PerThread,
235 src_loc: Zcu.LazySrcLoc,
236 lazy_sym: link.File.LazySymbol,229 lazy_sym: link.File.LazySymbol,
237 // TODO don't use an "out" parameter like this; put it in the result instead230 // TODO don't use an "out" parameter like this; put it in the result instead
238 alignment: *Alignment,231 alignment: *Alignment,
239 w: *std.Io.Writer,232 w: *std.Io.Writer,
240 debug_output: link.File.DebugInfoOutput,233 debug_output: link.File.DebugInfoOutput,
241 reloc_parent: link.File.RelocInfo.Parent,234 reloc_parent: link.File.RelocInfo.Parent,
242) (CodeGenError || std.Io.Writer.Error)!void {235) (Error || std.Io.Writer.Error)!void {
243 const tracy = trace(@src());236 const tracy = trace(@src());
244 defer tracy.end();237 defer tracy.end();
245 tracy.addTextFmt("{t}, {f}", .{ lazy_sym.kind, Type.fromInterned(lazy_sym.ty).fmt(pt) });238 tracy.addTextFmt("{t}, {f}", .{ lazy_sym.kind, Type.fromInterned(lazy_sym.ty).fmt(pt) });
...@@ -257,7 +250,7 @@ pub fn generateLazySymbol(...@@ -257,7 +250,7 @@ pub fn generateLazySymbol(
257250
258 if (lazy_sym.kind == .code) {251 if (lazy_sym.kind == .code) {
259 alignment.* = target_util.defaultFunctionAlignment(target);252 alignment.* = target_util.defaultFunctionAlignment(target);
260 return generateLazyFunction(bin_file, pt, src_loc, lazy_sym, reloc_parent.atom_index, w, debug_output);253 return generateLazyFunction(bin_file, pt, lazy_sym, reloc_parent.atom_index, w, debug_output);
261 }254 }
262255
263 if (lazy_sym.ty == .anyerror_type) {256 if (lazy_sym.ty == .anyerror_type) {
...@@ -295,22 +288,13 @@ pub fn generateLazySymbol(...@@ -295,22 +288,13 @@ pub fn generateLazySymbol(
295 }288 }
296}289}
297290
298pub const GenerateSymbolError = error{
299 OutOfMemory,
300 /// Compiler was asked to operate on a number larger than supported.
301 Overflow,
302 /// Compiler was asked to produce a non-byte-aligned relocation.
303 RelocationNotByteAligned,
304};
305
306pub fn generateSymbol(291pub fn generateSymbol(
307 bin_file: *link.File,292 bin_file: *link.File,
308 pt: Zcu.PerThread,293 pt: Zcu.PerThread,
309 src_loc: Zcu.LazySrcLoc,
310 val: Value,294 val: Value,
311 w: *std.Io.Writer,295 w: *std.Io.Writer,
312 reloc_parent: link.File.RelocInfo.Parent,296 reloc_parent: link.File.RelocInfo.Parent,
313) (GenerateSymbolError || std.Io.Writer.Error)!void {297) (Error || std.Io.Writer.Error)!void {
314 const tracy = trace(@src());298 const tracy = trace(@src());
315 defer tracy.end();299 defer tracy.end();
316300
...@@ -323,8 +307,11 @@ pub fn generateSymbol(...@@ -323,8 +307,11 @@ pub fn generateSymbol(
323307
324 log.debug("generateSymbol: val = {f}", .{val.fmtValue(pt)});308 log.debug("generateSymbol: val = {f}", .{val.fmtValue(pt)});
325309
310 const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse {
311 return zcu.comp.link_diags.fail("failed to generate symbol: type size overflow", .{});
312 };
313
326 if (val.isUndef(zcu)) {314 if (val.isUndef(zcu)) {
327 const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;
328 try w.splatByteAll(0xaa, abi_size);315 try w.splatByteAll(0xaa, abi_size);
329 return;316 return;
330 }317 }
...@@ -364,7 +351,6 @@ pub fn generateSymbol(...@@ -364,7 +351,6 @@ pub fn generateSymbol(
364 .enum_literal,351 .enum_literal,
365 => unreachable, // non-runtime values352 => unreachable, // non-runtime values
366 .int => {353 .int => {
367 const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;
368 var space: Value.BigIntSpace = undefined;354 var space: Value.BigIntSpace = undefined;
369 const int_val = val.toBigInt(&space, zcu);355 const int_val = val.toBigInt(&space, zcu);
370 int_val.writeTwosComplement(try w.writableSlice(abi_size), endian);356 int_val.writeTwosComplement(try w.writableSlice(abi_size), endian);
...@@ -397,13 +383,13 @@ pub fn generateSymbol(...@@ -397,13 +383,13 @@ pub fn generateSymbol(
397 // emit payload part of the error union383 // emit payload part of the error union
398 {384 {
399 const begin = w.end;385 const begin = w.end;
400 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(switch (error_union.val) {386 try generateSymbol(bin_file, pt, Value.fromInterned(switch (error_union.val) {
401 .err_name => try pt.intern(.{ .undef = payload_ty.toIntern() }),387 .err_name => try pt.intern(.{ .undef = payload_ty.toIntern() }),
402 .payload => |payload| payload,388 .payload => |payload| payload,
403 }), w, reloc_parent);389 }), w, reloc_parent);
404 const unpadded_end = w.end - begin;390 const unpadded_end = w.end - begin;
405 const padded_end = abi_align.forward(unpadded_end);391 const padded_end = abi_align.forward(unpadded_end);
406 const padding = math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow;392 const padding: usize = @intCast(padded_end - unpadded_end);
407393
408 if (padding > 0) {394 if (padding > 0) {
409 try w.splatByteAll(0, padding);395 try w.splatByteAll(0, padding);
...@@ -416,7 +402,7 @@ pub fn generateSymbol(...@@ -416,7 +402,7 @@ pub fn generateSymbol(
416 try w.writeInt(u16, err_val, endian);402 try w.writeInt(u16, err_val, endian);
417 const unpadded_end = w.end - begin;403 const unpadded_end = w.end - begin;
418 const padded_end = abi_align.forward(unpadded_end);404 const padded_end = abi_align.forward(unpadded_end);
419 const padding = math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow;405 const padding: usize = @intCast(padded_end - unpadded_end);
420406
421 if (padding > 0) {407 if (padding > 0) {
422 try w.splatByteAll(0, padding);408 try w.splatByteAll(0, padding);
...@@ -425,7 +411,7 @@ pub fn generateSymbol(...@@ -425,7 +411,7 @@ pub fn generateSymbol(
425 },411 },
426 .enum_tag => |enum_tag| {412 .enum_tag => |enum_tag| {
427 const int_tag_ty = ty.intTagType(zcu);413 const int_tag_ty = ty.intTagType(zcu);
428 try generateSymbol(bin_file, pt, src_loc, try pt.getCoerced(Value.fromInterned(enum_tag.int), int_tag_ty), w, reloc_parent);414 try generateSymbol(bin_file, pt, try pt.getCoerced(Value.fromInterned(enum_tag.int), int_tag_ty), w, reloc_parent);
429 },415 },
430 .float => |float| storage: switch (float.storage) {416 .float => |float| storage: switch (float.storage) {
431 .f16 => |f16_val| try w.writeInt(u16, @bitCast(f16_val), endian),417 .f16 => |f16_val| try w.writeInt(u16, @bitCast(f16_val), endian),
...@@ -433,7 +419,6 @@ pub fn generateSymbol(...@@ -433,7 +419,6 @@ pub fn generateSymbol(
433 .f64 => |f64_val| try w.writeInt(u64, @bitCast(f64_val), endian),419 .f64 => |f64_val| try w.writeInt(u64, @bitCast(f64_val), endian),
434 .f80 => |f80_val| {420 .f80 => |f80_val| {
435 try w.writeInt(u80, @bitCast(f80_val), endian);421 try w.writeInt(u80, @bitCast(f80_val), endian);
436 const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;
437 try w.splatByteAll(0, abi_size - 10);422 try w.splatByteAll(0, abi_size - 10);
438 },423 },
439 .f128 => |f128_val| switch (Type.fromInterned(float.ty).floatBits(target)) {424 .f128 => |f128_val| switch (Type.fromInterned(float.ty).floatBits(target)) {
...@@ -444,29 +429,28 @@ pub fn generateSymbol(...@@ -444,29 +429,28 @@ pub fn generateSymbol(
444 128 => try w.writeInt(u128, @bitCast(f128_val), endian),429 128 => try w.writeInt(u128, @bitCast(f128_val), endian),
445 },430 },
446 },431 },
447 .ptr => try lowerPtr(bin_file, pt, src_loc, val.toIntern(), w, reloc_parent, 0),432 .ptr => try lowerPtr(bin_file, pt, val.toIntern(), w, reloc_parent, 0),
448 .slice => |slice| {433 .slice => |slice| {
449 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(slice.ptr), w, reloc_parent);434 try generateSymbol(bin_file, pt, Value.fromInterned(slice.ptr), w, reloc_parent);
450 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(slice.len), w, reloc_parent);435 try generateSymbol(bin_file, pt, Value.fromInterned(slice.len), w, reloc_parent);
451 },436 },
452 .opt => {437 .opt => {
453 const payload_type = ty.optionalChild(zcu);438 const payload_type = ty.optionalChild(zcu);
454 const payload_val = val.optionalValue(zcu);439 const payload_val = val.optionalValue(zcu);
455 const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;
456440
457 if (ty.optionalReprIsPayload(zcu)) {441 if (ty.optionalReprIsPayload(zcu)) {
458 if (payload_val) |value| {442 if (payload_val) |value| {
459 try generateSymbol(bin_file, pt, src_loc, value, w, reloc_parent);443 try generateSymbol(bin_file, pt, value, w, reloc_parent);
460 } else {444 } else {
461 try w.splatByteAll(0, abi_size);445 try w.splatByteAll(0, abi_size);
462 }446 }
463 } else {447 } else {
464 const padding = abi_size - (math.cast(usize, payload_type.abiSize(zcu)) orelse return error.Overflow) - 1;448 const padding = abi_size - @as(usize, @intCast(payload_type.abiSize(zcu))) - 1;
465 if (payload_type.hasRuntimeBits(zcu)) {449 if (payload_type.hasRuntimeBits(zcu)) {
466 const value = payload_val orelse Value.fromInterned(try pt.intern(.{450 const value = payload_val orelse Value.fromInterned(try pt.intern(.{
467 .undef = payload_type.toIntern(),451 .undef = payload_type.toIntern(),
468 }));452 }));
469 try generateSymbol(bin_file, pt, src_loc, value, w, reloc_parent);453 try generateSymbol(bin_file, pt, value, w, reloc_parent);
470 }454 }
471 try w.writeByte(@intFromBool(payload_val != null));455 try w.writeByte(@intFromBool(payload_val != null));
472 try w.splatByteAll(0, padding);456 try w.splatByteAll(0, padding);
...@@ -478,7 +462,7 @@ pub fn generateSymbol(...@@ -478,7 +462,7 @@ pub fn generateSymbol(
478 .elems, .repeated_elem => {462 .elems, .repeated_elem => {
479 var index: u64 = 0;463 var index: u64 = 0;
480 while (index < array_type.lenIncludingSentinel()) : (index += 1) {464 while (index < array_type.lenIncludingSentinel()) : (index += 1) {
481 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(switch (aggregate.storage) {465 try generateSymbol(bin_file, pt, Value.fromInterned(switch (aggregate.storage) {
482 .bytes => unreachable,466 .bytes => unreachable,
483 .elems => |elems| elems[@intCast(index)],467 .elems => |elems| elems[@intCast(index)],
484 .repeated_elem => |elem| if (index < array_type.len)468 .repeated_elem => |elem| if (index < array_type.len)
...@@ -490,7 +474,6 @@ pub fn generateSymbol(...@@ -490,7 +474,6 @@ pub fn generateSymbol(
490 },474 },
491 },475 },
492 .vector_type => |vector_type| {476 .vector_type => |vector_type| {
493 const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;
494 const vector_bool_bitpacked = switch (zcu.comp.getZigBackend()) {477 const vector_bool_bitpacked = switch (zcu.comp.getZigBackend()) {
495 .stage2_wasm => false,478 .stage2_wasm => false,
496 else => true,479 else => true,
...@@ -499,7 +482,9 @@ pub fn generateSymbol(...@@ -499,7 +482,9 @@ pub fn generateSymbol(
499 const bytes = try w.writableSlice(abi_size);482 const bytes = try w.writableSlice(abi_size);
500 @memset(bytes, 0xaa);483 @memset(bytes, 0xaa);
501 var index: usize = 0;484 var index: usize = 0;
502 const len = math.cast(usize, vector_type.len) orelse return error.Overflow;485 const len = math.cast(usize, vector_type.len) orelse {
486 return zcu.comp.link_diags.fail("failed to generate symbol: vector length overflow", .{});
487 };
503 while (index < len) : (index += 1) {488 while (index < len) : (index += 1) {
504 const bit_index = switch (endian) {489 const bit_index = switch (endian) {
505 .big => len - 1 - index,490 .big => len - 1 - index,
...@@ -539,18 +524,16 @@ pub fn generateSymbol(...@@ -539,18 +524,16 @@ pub fn generateSymbol(
539 .elems, .repeated_elem => {524 .elems, .repeated_elem => {
540 var index: u64 = 0;525 var index: u64 = 0;
541 while (index < vector_type.len) : (index += 1) {526 while (index < vector_type.len) : (index += 1) {
542 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(switch (aggregate.storage) {527 try generateSymbol(bin_file, pt, Value.fromInterned(switch (aggregate.storage) {
543 .bytes => unreachable,528 .bytes => unreachable,
544 .elems => |elems| elems[math.cast(usize, index) orelse return error.Overflow],529 .elems => |elems| elems[@intCast(index)],
545 .repeated_elem => |elem| elem,530 .repeated_elem => |elem| elem,
546 }), w, reloc_parent);531 }), w, reloc_parent);
547 }532 }
548 },533 },
549 }534 }
550535
551 const padding = abi_size -536 const padding = abi_size - @as(usize, @intCast(Type.fromInterned(vector_type.child).abiSize(zcu) * vector_type.len));
552 (math.cast(usize, Type.fromInterned(vector_type.child).abiSize(zcu) * vector_type.len) orelse
553 return error.Overflow);
554 if (padding > 0) try w.splatByteAll(0, padding);537 if (padding > 0) try w.splatByteAll(0, padding);
555 }538 }
556 },539 },
...@@ -560,10 +543,9 @@ pub fn generateSymbol(...@@ -560,10 +543,9 @@ pub fn generateSymbol(
560 if (field_val != .none) continue;543 if (field_val != .none) continue;
561 if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue;544 if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue;
562545
563 try w.splatByteAll(0, math.cast(usize, struct_begin +546 try w.splatByteAll(0, @intCast(struct_begin +
564 Type.fromInterned(field_ty).abiAlignment(zcu).forward(w.end - struct_begin) - w.end) orelse547 Type.fromInterned(field_ty).abiAlignment(zcu).forward(w.end - struct_begin) - w.end));
565 return error.Overflow);548 try generateSymbol(bin_file, pt, .fromInterned(switch (aggregate.storage) {
566 try generateSymbol(bin_file, pt, src_loc, .fromInterned(switch (aggregate.storage) {
567 .bytes => |bytes| try pt.intern(.{ .int = .{549 .bytes => |bytes| try pt.intern(.{ .int = .{
568 .ty = field_ty,550 .ty = field_ty,
569 .storage = .{ .u64 = bytes.at(field_index, ip) },551 .storage = .{ .u64 = bytes.at(field_index, ip) },
...@@ -572,8 +554,7 @@ pub fn generateSymbol(...@@ -572,8 +554,7 @@ pub fn generateSymbol(
572 .repeated_elem => |elem| elem,554 .repeated_elem => |elem| elem,
573 }), w, reloc_parent);555 }), w, reloc_parent);
574 }556 }
575 try w.splatByteAll(0, math.cast(usize, struct_begin + ty.abiSize(zcu) - w.end) orelse557 try w.splatByteAll(0, @intCast(struct_begin + ty.abiSize(zcu) - w.end));
576 return error.Overflow);
577 },558 },
578 .struct_type => {559 .struct_type => {
579 const struct_type = ip.loadStructType(ty.toIntern());560 const struct_type = ip.loadStructType(ty.toIntern());
...@@ -598,20 +579,15 @@ pub fn generateSymbol(...@@ -598,20 +579,15 @@ pub fn generateSymbol(
598 .repeated_elem => |elem| elem,579 .repeated_elem => |elem| elem,
599 };580 };
600581
601 const padding = math.cast(582 const padding: usize = @intCast(offsets[field_index] - (w.end - struct_begin));
602 usize,
603 offsets[field_index] - (w.end - struct_begin),
604 ) orelse return error.Overflow;
605 if (padding > 0) try w.splatByteAll(0, padding);583 if (padding > 0) try w.splatByteAll(0, padding);
606584
607 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), w, reloc_parent);585 try generateSymbol(bin_file, pt, Value.fromInterned(field_val), w, reloc_parent);
608 }586 }
609587
610 assert(struct_type.alignment.check(struct_type.size));588 assert(struct_type.alignment.check(struct_type.size));
611589
612 const padding = math.cast(usize, struct_type.size - (w.end - struct_begin)) orelse {590 const padding: usize = @intCast(struct_type.size - (w.end - struct_begin));
613 return error.Overflow;
614 };
615 if (padding > 0) try w.splatByteAll(0, padding);591 if (padding > 0) try w.splatByteAll(0, padding);
616 },592 },
617 }593 }
...@@ -622,12 +598,12 @@ pub fn generateSymbol(...@@ -622,12 +598,12 @@ pub fn generateSymbol(
622 const layout = ty.unionGetLayout(zcu);598 const layout = ty.unionGetLayout(zcu);
623599
624 if (layout.payload_size == 0) {600 if (layout.payload_size == 0) {
625 return generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), w, reloc_parent);601 return generateSymbol(bin_file, pt, Value.fromInterned(un.tag), w, reloc_parent);
626 }602 }
627603
628 // Check if we should store the tag first.604 // Check if we should store the tag first.
629 if (layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)) {605 if (layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)) {
630 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), w, reloc_parent);606 try generateSymbol(bin_file, pt, Value.fromInterned(un.tag), w, reloc_parent);
631 }607 }
632608
633 const union_obj = zcu.typeToUnion(ty).?;609 const union_obj = zcu.typeToUnion(ty).?;
...@@ -635,28 +611,28 @@ pub fn generateSymbol(...@@ -635,28 +611,28 @@ pub fn generateSymbol(
635 const field_index = ty.unionTagFieldIndex(Value.fromInterned(un.tag), zcu).?;611 const field_index = ty.unionTagFieldIndex(Value.fromInterned(un.tag), zcu).?;
636 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);612 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
637 if (!field_ty.hasRuntimeBits(zcu)) {613 if (!field_ty.hasRuntimeBits(zcu)) {
638 try w.splatByteAll(0xaa, math.cast(usize, layout.payload_size) orelse return error.Overflow);614 try w.splatByteAll(0xaa, @intCast(layout.payload_size));
639 } else {615 } else {
640 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.val), w, reloc_parent);616 try generateSymbol(bin_file, pt, Value.fromInterned(un.val), w, reloc_parent);
641617
642 const padding = math.cast(usize, layout.payload_size - field_ty.abiSize(zcu)) orelse return error.Overflow;618 const padding: usize = @intCast(layout.payload_size - field_ty.abiSize(zcu));
643 if (padding > 0) {619 if (padding > 0) {
644 try w.splatByteAll(0, padding);620 try w.splatByteAll(0, padding);
645 }621 }
646 }622 }
647 } else {623 } else {
648 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.val), w, reloc_parent);624 try generateSymbol(bin_file, pt, Value.fromInterned(un.val), w, reloc_parent);
649 }625 }
650626
651 if (layout.tag_size > 0 and layout.tag_align.compare(.lt, layout.payload_align)) {627 if (layout.tag_size > 0 and layout.tag_align.compare(.lt, layout.payload_align)) {
652 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), w, reloc_parent);628 try generateSymbol(bin_file, pt, Value.fromInterned(un.tag), w, reloc_parent);
653629
654 if (layout.padding > 0) {630 if (layout.padding > 0) {
655 try w.splatByteAll(0, layout.padding);631 try w.splatByteAll(0, layout.padding);
656 }632 }
657 }633 }
658 },634 },
659 .bitpack => |bitpack| try generateSymbol(bin_file, pt, src_loc, .fromInterned(bitpack.backing_int_val), w, reloc_parent),635 .bitpack => |bitpack| try generateSymbol(bin_file, pt, .fromInterned(bitpack.backing_int_val), w, reloc_parent),
660 .memoized_call => unreachable,636 .memoized_call => unreachable,
661 }637 }
662}638}
...@@ -664,23 +640,21 @@ pub fn generateSymbol(...@@ -664,23 +640,21 @@ pub fn generateSymbol(
664fn lowerPtr(640fn lowerPtr(
665 bin_file: *link.File,641 bin_file: *link.File,
666 pt: Zcu.PerThread,642 pt: Zcu.PerThread,
667 src_loc: Zcu.LazySrcLoc,
668 ptr_val: InternPool.Index,643 ptr_val: InternPool.Index,
669 w: *std.Io.Writer,644 w: *std.Io.Writer,
670 reloc_parent: link.File.RelocInfo.Parent,645 reloc_parent: link.File.RelocInfo.Parent,
671 prev_offset: u64,646 prev_offset: u64,
672) (GenerateSymbolError || std.Io.Writer.Error)!void {647) (Error || std.Io.Writer.Error)!void {
673 const zcu = pt.zcu;648 const zcu = pt.zcu;
674 const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr;649 const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr;
675 const offset: u64 = prev_offset + ptr.byte_offset;650 const offset: u64 = prev_offset + ptr.byte_offset;
676 return switch (ptr.base_addr) {651 return switch (ptr.base_addr) {
677 .nav => |nav| try lowerNavRef(bin_file, pt, nav, w, reloc_parent, offset),652 .nav => |nav| try lowerNavRef(bin_file, pt, nav, w, reloc_parent, offset),
678 .uav => |uav| try lowerUavRef(bin_file, pt, src_loc, uav, w, reloc_parent, offset),653 .uav => |uav| try lowerUavRef(bin_file, pt, uav, w, reloc_parent, offset),
679 .int => try generateSymbol(bin_file, pt, src_loc, try pt.intValue(Type.usize, offset), w, reloc_parent),654 .int => try generateSymbol(bin_file, pt, try pt.intValue(Type.usize, offset), w, reloc_parent),
680 .eu_payload => |eu_ptr| try lowerPtr(655 .eu_payload => |eu_ptr| try lowerPtr(
681 bin_file,656 bin_file,
682 pt,657 pt,
683 src_loc,
684 eu_ptr,658 eu_ptr,
685 w,659 w,
686 reloc_parent,660 reloc_parent,
...@@ -689,7 +663,7 @@ fn lowerPtr(...@@ -689,7 +663,7 @@ fn lowerPtr(
689 zcu,663 zcu,
690 ),664 ),
691 ),665 ),
692 .opt_payload => |opt_ptr| try lowerPtr(bin_file, pt, src_loc, opt_ptr, w, reloc_parent, offset),666 .opt_payload => |opt_ptr| try lowerPtr(bin_file, pt, opt_ptr, w, reloc_parent, offset),
693 .field => |field| {667 .field => |field| {
694 const base_ptr = Value.fromInterned(field.base);668 const base_ptr = Value.fromInterned(field.base);
695 const base_ty = base_ptr.typeOf(zcu).childType(zcu);669 const base_ty = base_ptr.typeOf(zcu).childType(zcu);
...@@ -708,13 +682,13 @@ fn lowerPtr(...@@ -708,13 +682,13 @@ fn lowerPtr(
708 },682 },
709 else => unreachable,683 else => unreachable,
710 };684 };
711 return lowerPtr(bin_file, pt, src_loc, field.base, w, reloc_parent, offset + field_off);685 return lowerPtr(bin_file, pt, field.base, w, reloc_parent, offset + field_off);
712 },686 },
713 .arr_elem => |arr_elem| {687 .arr_elem => |arr_elem| {
714 const base_ptr_ty = Value.fromInterned(arr_elem.base).typeOf(zcu);688 const base_ptr_ty = Value.fromInterned(arr_elem.base).typeOf(zcu);
715 assert(base_ptr_ty.ptrSize(zcu) == .many);689 assert(base_ptr_ty.ptrSize(zcu) == .many);
716 const elem_size = base_ptr_ty.childType(zcu).abiSize(zcu);690 const elem_size = base_ptr_ty.childType(zcu).abiSize(zcu);
717 return lowerPtr(bin_file, pt, src_loc, arr_elem.base, w, reloc_parent, offset + elem_size * arr_elem.index);691 return lowerPtr(bin_file, pt, arr_elem.base, w, reloc_parent, offset + elem_size * arr_elem.index);
718 },692 },
719 .comptime_alloc => unreachable,693 .comptime_alloc => unreachable,
720 .comptime_field => unreachable,694 .comptime_field => unreachable,
...@@ -724,12 +698,11 @@ fn lowerPtr(...@@ -724,12 +698,11 @@ fn lowerPtr(
724fn lowerUavRef(698fn lowerUavRef(
725 lf: *link.File,699 lf: *link.File,
726 pt: Zcu.PerThread,700 pt: Zcu.PerThread,
727 src_loc: Zcu.LazySrcLoc,
728 uav: InternPool.Key.Ptr.BaseAddr.Uav,701 uav: InternPool.Key.Ptr.BaseAddr.Uav,
729 w: *std.Io.Writer,702 w: *std.Io.Writer,
730 reloc_parent: link.File.RelocInfo.Parent,703 reloc_parent: link.File.RelocInfo.Parent,
731 offset: u64,704 offset: u64,
732) (GenerateSymbolError || std.Io.Writer.Error)!void {705) (Error || std.Io.Writer.Error)!void {
733 const zcu = pt.zcu;706 const zcu = pt.zcu;
734 const ip = &zcu.intern_pool;707 const ip = &zcu.intern_pool;
735 const comp = lf.comp;708 const comp = lf.comp;
...@@ -761,10 +734,7 @@ fn lowerUavRef(...@@ -761,10 +734,7 @@ fn lowerUavRef(
761 }734 }
762735
763 const uav_align = Type.fromInterned(uav.orig_ty).ptrAlignment(zcu);736 const uav_align = Type.fromInterned(uav.orig_ty).ptrAlignment(zcu);
764 switch (try lf.lowerUav(pt, uav_val, uav_align, src_loc)) {737 _ = try lf.lowerUav(pt, uav_val, uav_align);
765 .sym_index => {},
766 .fail => |em| std.debug.panic("TODO rework lowerUav. internal error: {s}", .{em.msg}),
767 }
768738
769 const vaddr = lf.getUavVAddr(uav_val, .{739 const vaddr = lf.getUavVAddr(uav_val, .{
770 .parent = reloc_parent,740 .parent = reloc_parent,
...@@ -790,7 +760,7 @@ fn lowerNavRef(...@@ -790,7 +760,7 @@ fn lowerNavRef(
790 w: *std.Io.Writer,760 w: *std.Io.Writer,
791 reloc_parent: link.File.RelocInfo.Parent,761 reloc_parent: link.File.RelocInfo.Parent,
792 offset: u64,762 offset: u64,
793) (GenerateSymbolError || std.Io.Writer.Error)!void {763) (Error || std.Io.Writer.Error)!void {
794 const zcu = pt.zcu;764 const zcu = pt.zcu;
795 const gpa = zcu.gpa;765 const gpa = zcu.gpa;
796 const ip = &zcu.intern_pool;766 const ip = &zcu.intern_pool;
...@@ -859,15 +829,11 @@ fn lowerNavRef(...@@ -859,15 +829,11 @@ fn lowerNavRef(
859 }829 }
860}830}
861831
862pub const SymbolResult = union(enum) { sym_index: link.File.SymbolId, fail: *ErrorMsg };
863
864pub fn genNavRef(832pub fn genNavRef(
865 lf: *link.File,833 lf: *link.File,
866 pt: Zcu.PerThread,834 pt: Zcu.PerThread,
867 src_loc: Zcu.LazySrcLoc,
868 nav_index: InternPool.Nav.Index,835 nav_index: InternPool.Nav.Index,
869 target: *const std.Target,836) Error!link.File.SymbolId {
870) CodeGenError!SymbolResult {
871 const zcu = pt.zcu;837 const zcu = pt.zcu;
872 const ip = &zcu.intern_pool;838 const ip = &zcu.intern_pool;
873 const nav = ip.getNav(nav_index);839 const nav = ip.getNav(nav_index);
...@@ -884,7 +850,7 @@ pub fn genNavRef(...@@ -884,7 +850,7 @@ pub fn genNavRef(
884 .internal => {850 .internal => {
885 const sym_index = try zo.getOrCreateMetadataForNav(zcu, nav_index);851 const sym_index = try zo.getOrCreateMetadataForNav(zcu, nav_index);
886 if (is_threadlocal) zo.symbol(sym_index).flags.is_tls = true;852 if (is_threadlocal) zo.symbol(sym_index).flags.is_tls = true;
887 return .{ .sym_index = @enumFromInt(sym_index) };853 return @enumFromInt(sym_index);
888 },854 },
889 .strong, .weak => {855 .strong, .weak => {
890 const sym_index = try elf_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));856 const sym_index = try elf_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));
...@@ -895,27 +861,19 @@ pub fn genNavRef(...@@ -895,27 +861,19 @@ pub fn genNavRef(
895 .link_once => unreachable,861 .link_once => unreachable,
896 }862 }
897 if (is_threadlocal) zo.symbol(sym_index).flags.is_tls = true;863 if (is_threadlocal) zo.symbol(sym_index).flags.is_tls = true;
898 return .{ .sym_index = @enumFromInt(sym_index) };864 return @enumFromInt(sym_index);
899 },865 },
900 .link_once => unreachable,866 .link_once => unreachable,
901 }867 }
902 } else if (lf.cast(.elf2)) |elf| {868 } else if (lf.cast(.elf2)) |elf| {
903 return .{ .sym_index = elf.navSymbol(nav_index) catch |err| switch (err) {869 return elf.navSymbol(nav_index);
904 error.OutOfMemory => |e| return e,
905 else => |e| return .{ .fail = try ErrorMsg.create(
906 zcu.gpa,
907 src_loc,
908 "linker failed to create a nav: {t}",
909 .{e},
910 ) },
911 } };
912 } else if (lf.cast(.macho)) |macho_file| {870 } else if (lf.cast(.macho)) |macho_file| {
913 const zo = macho_file.getZigObject().?;871 const zo = macho_file.getZigObject().?;
914 switch (linkage) {872 switch (linkage) {
915 .internal => {873 .internal => {
916 const sym_index = try zo.getOrCreateMetadataForNav(macho_file, nav_index);874 const sym_index = try zo.getOrCreateMetadataForNav(macho_file, nav_index);
917 if (is_threadlocal) zo.symbols.items[sym_index].flags.tlv = true;875 if (is_threadlocal) zo.symbols.items[sym_index].flags.tlv = true;
918 return .{ .sym_index = @enumFromInt(sym_index) };876 return @enumFromInt(sym_index);
919 },877 },
920 .strong, .weak => {878 .strong, .weak => {
921 const sym_index = try macho_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));879 const sym_index = try macho_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));
...@@ -926,80 +884,67 @@ pub fn genNavRef(...@@ -926,80 +884,67 @@ pub fn genNavRef(
926 .link_once => unreachable,884 .link_once => unreachable,
927 }885 }
928 if (is_threadlocal) zo.symbols.items[sym_index].flags.tlv = true;886 if (is_threadlocal) zo.symbols.items[sym_index].flags.tlv = true;
929 return .{ .sym_index = @enumFromInt(sym_index) };887 return @enumFromInt(sym_index);
930 },888 },
931 .link_once => unreachable,889 .link_once => unreachable,
932 }890 }
933 } else if (lf.cast(.coff2)) |coff| {891 } else if (lf.cast(.coff2)) |coff| {
934 return .{ .sym_index = @enumFromInt(@intFromEnum(try coff.navSymbol(zcu, nav_index))) };892 return @enumFromInt(@intFromEnum(try coff.navSymbol(zcu, nav_index)));
935 } else {893 } else {
936 const msg = try ErrorMsg.create(zcu.gpa, src_loc, "TODO genNavRef for target {}", .{target});894 std.debug.panic("TODO genNavRef for '{t}'", .{lf.tag});
937 return .{ .fail = msg };
938 }895 }
939}896}
940897
941/// deprecated legacy type898/// deprecated legacy type
942pub const GenResult = union(enum) {899pub const MCValue = union(enum) {
943 mcv: MCValue,900 none,
944 fail: *ErrorMsg,901 undef,
945902 /// The bit-width of the immediate may be smaller than `u64`. For example, on 32-bit targets
946 const MCValue = union(enum) {903 /// such as ARM, the immediate will never exceed 32-bits.
947 none,904 immediate: u64,
948 undef,905 /// Decl with address deferred until the linker allocates everything in virtual memory.
949 /// The bit-width of the immediate may be smaller than `u64`. For example, on 32-bit targets906 /// Payload is a symbol index.
950 /// such as ARM, the immediate will never exceed 32-bits.907 load_direct: link.File.SymbolId,
951 immediate: u64,908 /// Decl with address deferred until the linker allocates everything in virtual memory.
952 /// Decl with address deferred until the linker allocates everything in virtual memory.909 /// Payload is a symbol index.
953 /// Payload is a symbol index.910 lea_direct: link.File.SymbolId,
954 load_direct: link.File.SymbolId,911 /// Decl referenced via GOT with address deferred until the linker allocates
955 /// Decl with address deferred until the linker allocates everything in virtual memory.912 /// everything in virtual memory.
956 /// Payload is a symbol index.913 /// Payload is a symbol index.
957 lea_direct: link.File.SymbolId,914 load_got: link.File.SymbolId,
958 /// Decl referenced via GOT with address deferred until the linker allocates915 /// Direct by-address reference to memory location.
959 /// everything in virtual memory.916 memory: u64,
960 /// Payload is a symbol index.917 /// Reference to memory location but deferred until linker allocated the Decl in memory.
961 load_got: link.File.SymbolId,918 /// Traditionally, this corresponds to emitting a relocation in a relocatable object file.
962 /// Direct by-address reference to memory location.919 load_symbol: link.File.SymbolId,
963 memory: u64,920 /// Reference to memory location but deferred until linker allocated the Decl in memory.
964 /// Reference to memory location but deferred until linker allocated the Decl in memory.921 /// Traditionally, this corresponds to emitting a relocation in a relocatable object file.
965 /// Traditionally, this corresponds to emitting a relocation in a relocatable object file.922 lea_symbol: link.File.SymbolId,
966 load_symbol: link.File.SymbolId,
967 /// Reference to memory location but deferred until linker allocated the Decl in memory.
968 /// Traditionally, this corresponds to emitting a relocation in a relocatable object file.
969 lea_symbol: link.File.SymbolId,
970 };
971};923};
972924
973/// deprecated legacy code path925/// deprecated legacy code path
974pub fn genTypedValue(926pub fn genTypedValue(
975 lf: *link.File,927 lf: *link.File,
976 pt: Zcu.PerThread,928 pt: Zcu.PerThread,
977 src_loc: Zcu.LazySrcLoc,
978 val: Value,929 val: Value,
979 target: *const std.Target,930 target: *const std.Target,
980) CodeGenError!GenResult {931) Error!MCValue {
981 const res = try lowerValue(pt, val, target);932 const res = try lowerValue(pt, val, target);
982 return switch (res) {933 return switch (res) {
983 .none => .{ .mcv = .none },934 .none => .none,
984 .undef => .{ .mcv = .undef },935 .undef => .undef,
985 .immediate => |imm| .{ .mcv = .{ .immediate = imm } },936 .immediate => |imm| .{ .immediate = imm },
986 .lea_nav => |nav| switch (try genNavRef(lf, pt, src_loc, nav, target)) {937 .lea_nav => |nav| .{ .lea_symbol = try genNavRef(lf, pt, nav) },
987 .sym_index => |sym_index| .{ .mcv = .{ .lea_symbol = sym_index } },938 .load_uav => |uav| .{ .load_symbol = try lf.lowerUav(
988 .fail => |em| .{ .fail = em },
989 },
990 .load_uav, .lea_uav => |uav| switch (try lf.lowerUav(
991 pt,939 pt,
992 uav.val,940 uav.val,
993 Type.fromInterned(uav.orig_ty).ptrAlignment(pt.zcu),941 Type.fromInterned(uav.orig_ty).ptrAlignment(pt.zcu),
994 src_loc,942 ) },
995 )) {943 .lea_uav => |uav| .{ .lea_symbol = try lf.lowerUav(
996 .sym_index => |sym_index| .{ .mcv = switch (res) {944 pt,
997 else => unreachable,945 uav.val,
998 .load_uav => .{ .load_symbol = sym_index },946 Type.fromInterned(uav.orig_ty).ptrAlignment(pt.zcu),
999 .lea_uav => .{ .lea_symbol = sym_index },947 ) },
1000 } },
1001 .fail => |em| .{ .fail = em },
1002 },
1003 };948 };
1004}949}
1005950
src/codegen/aarch64.zig-1
...@@ -12,7 +12,6 @@ pub fn legalizeFeatures(_: *const std.Target) ?*Air.Legalize.Features {...@@ -12,7 +12,6 @@ pub fn legalizeFeatures(_: *const std.Target) ?*Air.Legalize.Features {
12pub fn generate(12pub fn generate(
13 _: *link.File,13 _: *link.File,
14 pt: Zcu.PerThread,14 pt: Zcu.PerThread,
15 _: Zcu.LazySrcLoc,
16 func_index: InternPool.Index,15 func_index: InternPool.Index,
17 air: *const Air,16 air: *const Air,
18 liveness: *const ?Air.Liveness,17 liveness: *const ?Air.Liveness,
src/codegen/aarch64/Mir.zig+4-14
...@@ -54,7 +54,6 @@ pub fn emit(...@@ -54,7 +54,6 @@ pub fn emit(
54 mir: Mir,54 mir: Mir,
55 lf: *link.File,55 lf: *link.File,
56 pt: Zcu.PerThread,56 pt: Zcu.PerThread,
57 src_loc: Zcu.LazySrcLoc,
58 func_index: InternPool.Index,57 func_index: InternPool.Index,
59 atom_index: link.File.AtomId,58 atom_index: link.File.AtomId,
60 w: *std.Io.Writer,59 w: *std.Io.Writer,
...@@ -94,16 +93,11 @@ pub fn emit(...@@ -94,16 +93,11 @@ pub fn emit(
94 lf,93 lf,
95 zcu,94 zcu,
96 atom_index,95 atom_index,
97 switch (try @import("../../codegen.zig").genNavRef(96 try @import("../../codegen.zig").genNavRef(
98 lf,97 lf,
99 pt,98 pt,
100 src_loc,
101 nav_reloc.nav,99 nav_reloc.nav,
102 &mod.resolved_target.result,100 ),
103 )) {
104 .sym_index => |sym_index| sym_index,
105 .fail => |em| return zcu.codegenFailMsg(func.owner_nav, em),
106 },
107 mir.body[nav_reloc.reloc.label],101 mir.body[nav_reloc.reloc.label],
108 body_end - Instruction.size * (1 + nav_reloc.reloc.label),102 body_end - Instruction.size * (1 + nav_reloc.reloc.label),
109 nav_reloc.reloc.addend,103 nav_reloc.reloc.addend,
...@@ -113,15 +107,11 @@ pub fn emit(...@@ -113,15 +107,11 @@ pub fn emit(
113 lf,107 lf,
114 zcu,108 zcu,
115 atom_index,109 atom_index,
116 switch (try lf.lowerUav(110 try lf.lowerUav(
117 pt,111 pt,
118 uav_reloc.uav.val,112 uav_reloc.uav.val,
119 ZigType.fromInterned(uav_reloc.uav.orig_ty).ptrAlignment(zcu),113 ZigType.fromInterned(uav_reloc.uav.orig_ty).ptrAlignment(zcu),
120 src_loc,114 ),
121 )) {
122 .sym_index => |sym_index| sym_index,
123 .fail => |em| return zcu.codegenFailMsg(func.owner_nav, em),
124 },
125 mir.body[uav_reloc.reloc.label],115 mir.body[uav_reloc.reloc.label],
126 body_end - Instruction.size * (1 + uav_reloc.reloc.label),116 body_end - Instruction.size * (1 + uav_reloc.reloc.label),
127 uav_reloc.reloc.addend,117 uav_reloc.reloc.addend,
src/codegen/aarch64/Select.zig+5-5
...@@ -883,7 +883,7 @@ pub fn finishAnalysis(isel: *Select) !void {...@@ -883,7 +883,7 @@ pub fn finishAnalysis(isel: *Select) !void {
883 }883 }
884}884}
885885
886pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, CodegenFail }!void {886pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, AlreadyReported }!void {
887 const zcu = isel.pt.zcu;887 const zcu = isel.pt.zcu;
888 const ip = &zcu.intern_pool;888 const ip = &zcu.intern_pool;
889 const gpa = zcu.gpa;889 const gpa = zcu.gpa;
...@@ -8001,7 +8001,7 @@ fn emitLiteral(isel: *Select, bytes: []const u8) !void {...@@ -8001,7 +8001,7 @@ fn emitLiteral(isel: *Select, bytes: []const u8) !void {
8001 }8001 }
8002}8002}
80038003
8004fn fail(isel: *Select, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {8004fn fail(isel: *Select, comptime format: []const u8, args: anytype) error{ OutOfMemory, AlreadyReported } {
8005 @branchHint(.cold);8005 @branchHint(.cold);
8006 return isel.pt.zcu.codegenFail(isel.nav_index, format, args);8006 return isel.pt.zcu.codegenFail(isel.nav_index, format, args);
8007}8007}
...@@ -10595,7 +10595,7 @@ pub const Value = struct {...@@ -10595,7 +10595,7 @@ pub const Value = struct {
10595 vi: Value.Index,10595 vi: Value.Index,
10596 ra: Register.Alias,10596 ra: Register.Alias,
1059710597
10598 fn finish(mat: Value.Materialize, isel: *Select) error{ OutOfMemory, CodegenFail }!void {10598 fn finish(mat: Value.Materialize, isel: *Select) error{ OutOfMemory, AlreadyReported }!void {
10599 const live_vi = isel.live_registers.getPtr(mat.ra);10599 const live_vi = isel.live_registers.getPtr(mat.ra);
10600 assert(live_vi.* == .allocating);10600 assert(live_vi.* == .allocating);
10601 var vi = mat.vi;10601 var vi = mat.vi;
...@@ -11636,7 +11636,7 @@ fn use(isel: *Select, air_ref: Air.Inst.Ref) !Value.Index {...@@ -11636,7 +11636,7 @@ fn use(isel: *Select, air_ref: Air.Inst.Ref) !Value.Index {
11636 return vi;11636 return vi;
11637}11637}
1163811638
11639fn fill(isel: *Select, dst_ra: Register.Alias) error{ OutOfMemory, CodegenFail }!bool {11639fn fill(isel: *Select, dst_ra: Register.Alias) error{ OutOfMemory, AlreadyReported }!bool {
11640 switch (dst_ra) {11640 switch (dst_ra) {
11641 else => {},11641 else => {},
11642 Register.Alias.fp, .zr, .sp, .pc, .fpcr, .fpsr, .ffr => return false,11642 Register.Alias.fp, .zr, .sp, .pc, .fpcr, .fpsr, .ffr => return false,
...@@ -11669,7 +11669,7 @@ fn fill(isel: *Select, dst_ra: Register.Alias) error{ OutOfMemory, CodegenFail }...@@ -11669,7 +11669,7 @@ fn fill(isel: *Select, dst_ra: Register.Alias) error{ OutOfMemory, CodegenFail }
11669 return true;11669 return true;
11670}11670}
1167111671
11672fn fillMemory(isel: *Select, dst_ra: Register.Alias) error{ OutOfMemory, CodegenFail }!bool {11672fn fillMemory(isel: *Select, dst_ra: Register.Alias) error{ OutOfMemory, AlreadyReported }!bool {
11673 const dst_live_vi = isel.live_registers.getPtr(dst_ra);11673 const dst_live_vi = isel.live_registers.getPtr(dst_ra);
11674 const dst_vi = switch (dst_live_vi.*) {11674 const dst_vi = switch (dst_live_vi.*) {
11675 _ => |dst_vi| dst_vi,11675 _ => |dst_vi| dst_vi,
src/codegen/c.zig+4-12
...@@ -80,7 +80,7 @@ pub const Mir = struct {...@@ -80,7 +80,7 @@ pub const Mir = struct {
80 }80 }
81};81};
8282
83pub const Error = Writer.Error || Allocator.Error || error{AnalysisFail};83pub const Error = Writer.Error || Allocator.Error || error{AlreadyReported};
8484
85pub const CType = @import("c/type.zig").CType;85pub const CType = @import("c/type.zig").CType;
8686
...@@ -637,7 +637,6 @@ pub const DeclGen = struct {...@@ -637,7 +637,6 @@ pub const DeclGen = struct {
637 owner_nav: InternPool.Nav.Index.Optional,637 owner_nav: InternPool.Nav.Index.Optional,
638 is_naked_fn: bool,638 is_naked_fn: bool,
639 expected_block: ?u32,639 expected_block: ?u32,
640 error_msg: ?*Zcu.ErrorMsg,
641 ctype_deps: CType.Dependencies,640 ctype_deps: CType.Dependencies,
642 /// This map contains all the UAVs we saw generating this function.641 /// This map contains all the UAVs we saw generating this function.
643 /// `link.C` will merge them into its `uavs`/`aligned_uavs` fields.642 /// `link.C` will merge them into its `uavs`/`aligned_uavs` fields.
...@@ -648,10 +647,7 @@ pub const DeclGen = struct {...@@ -648,10 +647,7 @@ pub const DeclGen = struct {
648647
649 fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) Error {648 fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) Error {
650 @branchHint(.cold);649 @branchHint(.cold);
651 const zcu = dg.pt.zcu;650 return dg.pt.zcu.codegenFail(dg.owner_nav.unwrap().?, format, args);
652 const src_loc = zcu.navSrcLoc(dg.owner_nav.unwrap().?);
653 dg.error_msg = try Zcu.ErrorMsg.create(dg.gpa, src_loc, format, args);
654 return error.AnalysisFail;
655 }651 }
656652
657 fn renderUav(653 fn renderUav(
...@@ -2184,15 +2180,13 @@ pub fn genLazyCallModifierFn(...@@ -2184,15 +2180,13 @@ pub fn genLazyCallModifierFn(
2184pub fn generate(2180pub fn generate(
2185 lf: *link.File,2181 lf: *link.File,
2186 pt: Zcu.PerThread,2182 pt: Zcu.PerThread,
2187 src_loc: Zcu.LazySrcLoc,
2188 func_index: InternPool.Index,2183 func_index: InternPool.Index,
2189 air: *const Air,2184 air: *const Air,
2190 liveness: *const ?Air.Liveness,2185 liveness: *const ?Air.Liveness,
2191) @import("../codegen.zig").CodeGenError!Mir {2186) @import("../codegen.zig").Error!Mir {
2192 const zcu = pt.zcu;2187 const zcu = pt.zcu;
2193 const gpa = zcu.gpa;2188 const gpa = zcu.gpa;
21942189
2195 _ = src_loc;
2196 assert(lf.tag == .c);2190 assert(lf.tag == .c);
21972191
2198 const func = zcu.funcInfo(func_index);2192 const func = zcu.funcInfo(func_index);
...@@ -2210,7 +2204,6 @@ pub fn generate(...@@ -2210,7 +2204,6 @@ pub fn generate(
2210 .arena = arena.allocator(),2204 .arena = arena.allocator(),
2211 .pt = pt,2205 .pt = pt,
2212 .mod = zcu.navFileScope(func.owner_nav).mod.?,2206 .mod = zcu.navFileScope(func.owner_nav).mod.?,
2213 .error_msg = null,
2214 .owner_nav = func.owner_nav.toOptional(),2207 .owner_nav = func.owner_nav.toOptional(),
2215 .is_naked_fn = Type.fromInterned(func.ty).fnCallingConvention(zcu) == .naked,2208 .is_naked_fn = Type.fromInterned(func.ty).fnCallingConvention(zcu) == .naked,
2216 .expected_block = null,2209 .expected_block = null,
...@@ -2237,9 +2230,8 @@ pub fn generate(...@@ -2237,9 +2230,8 @@ pub fn generate(
2237 defer code_header.deinit();2230 defer code_header.deinit();
22382231
2239 genFunc(&function, &fwd_decl.writer, &code_header.writer) catch |err| switch (err) {2232 genFunc(&function, &fwd_decl.writer, &code_header.writer) catch |err| switch (err) {
2240 error.AnalysisFail => return zcu.codegenFailMsg(func.owner_nav, function.dg.error_msg.?),
2241 error.WriteFailed => return error.OutOfMemory,2233 error.WriteFailed => return error.OutOfMemory,
2242 error.OutOfMemory => |e| return e,2234 else => |e| return e,
2243 };2235 };
22442236
2245 var mir: Mir = .{2237 var mir: Mir = .{
src/codegen/llvm.zig+3-3
...@@ -771,7 +771,7 @@ pub const Object = struct {...@@ -771,7 +771,7 @@ pub const Object = struct {
771 lto: std.zig.LtoMode,771 lto: std.zig.LtoMode,
772 };772 };
773773
774 pub fn emit(o: *Object, pt: Zcu.PerThread, options: EmitOptions) error{ LinkFailure, OutOfMemory }!void {774 pub fn emit(o: *Object, pt: Zcu.PerThread, options: EmitOptions) error{ AlreadyReported, OutOfMemory }!void {
775 const zcu = o.zcu;775 const zcu = o.zcu;
776 const comp = zcu.comp;776 const comp = zcu.comp;
777 const io = comp.io;777 const io = comp.io;
...@@ -1705,7 +1705,7 @@ pub const Object = struct {...@@ -1705,7 +1705,7 @@ pub const Object = struct {
1705 o: *Object,1705 o: *Object,
1706 exported: Zcu.Exported,1706 exported: Zcu.Exported,
1707 export_indices: []const Zcu.Export.Index,1707 export_indices: []const Zcu.Export.Index,
1708 ) link.File.UpdateExportsError!void {1708 ) link.Error!void {
1709 const zcu = o.zcu;1709 const zcu = o.zcu;
1710 const ip = &zcu.intern_pool;1710 const ip = &zcu.intern_pool;
1711 const ty: Type, const llvm_ptr: Builder.Constant = switch (exported) {1711 const ty: Type, const llvm_ptr: Builder.Constant = switch (exported) {
...@@ -1735,7 +1735,7 @@ pub const Object = struct {...@@ -1735,7 +1735,7 @@ pub const Object = struct {
1735 global_index: Builder.Global.Index,1735 global_index: Builder.Global.Index,
1736 ty: Type,1736 ty: Type,
1737 export_indices: []const Zcu.Export.Index,1737 export_indices: []const Zcu.Export.Index,
1738 ) link.File.UpdateExportsError!void {1738 ) link.Error!void {
1739 const zcu = o.zcu;1739 const zcu = o.zcu;
1740 const comp = zcu.comp;1740 const comp = zcu.comp;
1741 const ip = &zcu.intern_pool;1741 const ip = &zcu.intern_pool;
src/codegen/riscv64/CodeGen.zig+24-40
...@@ -30,8 +30,6 @@ const verbose_tracking_log = std.log.scoped(.verbose_tracking);...@@ -30,8 +30,6 @@ const verbose_tracking_log = std.log.scoped(.verbose_tracking);
30const wip_mir_log = std.log.scoped(.wip_mir);30const wip_mir_log = std.log.scoped(.wip_mir);
31const Alignment = InternPool.Alignment;31const Alignment = InternPool.Alignment;
3232
33const CodeGenError = codegen.CodeGenError;
34
35const bits = @import("bits.zig");33const bits = @import("bits.zig");
36const abi = @import("abi.zig");34const abi = @import("abi.zig");
37const Lower = @import("Lower.zig");35const Lower = @import("Lower.zig");
...@@ -49,7 +47,7 @@ const RegisterManager = abi.RegisterManager;...@@ -49,7 +47,7 @@ const RegisterManager = abi.RegisterManager;
49const RegisterLock = RegisterManager.RegisterLock;47const RegisterLock = RegisterManager.RegisterLock;
50const Instruction = encoding.Instruction;48const Instruction = encoding.Instruction;
5149
52const InnerError = CodeGenError || error{OutOfRegisters};50const InnerError = codegen.Error || error{OutOfRegisters};
5351
54pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {52pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
55 return comptime &.initMany(&.{53 return comptime &.initMany(&.{
...@@ -75,7 +73,6 @@ ret_mcv: InstTracking,...@@ -75,7 +73,6 @@ ret_mcv: InstTracking,
75func_index: InternPool.Index,73func_index: InternPool.Index,
76fn_type: Type,74fn_type: Type,
77arg_index: usize,75arg_index: usize,
78src_loc: Zcu.LazySrcLoc,
7976
80mir_instructions: std.MultiArrayList(Mir.Inst) = .{},77mir_instructions: std.MultiArrayList(Mir.Inst) = .{},
8178
...@@ -742,11 +739,10 @@ const CallView = enum(u1) {...@@ -742,11 +739,10 @@ const CallView = enum(u1) {
742pub fn generate(739pub fn generate(
743 bin_file: *link.File,740 bin_file: *link.File,
744 pt: Zcu.PerThread,741 pt: Zcu.PerThread,
745 src_loc: Zcu.LazySrcLoc,
746 func_index: InternPool.Index,742 func_index: InternPool.Index,
747 air: *const Air,743 air: *const Air,
748 liveness: *const ?Air.Liveness,744 liveness: *const ?Air.Liveness,
749) CodeGenError!Mir {745) codegen.Error!Mir {
750 const zcu = pt.zcu;746 const zcu = pt.zcu;
751 const gpa = zcu.gpa;747 const gpa = zcu.gpa;
752 const ip = &zcu.intern_pool;748 const ip = &zcu.intern_pool;
...@@ -777,7 +773,6 @@ pub fn generate(...@@ -777,7 +773,6 @@ pub fn generate(
777 .fn_type = fn_type,773 .fn_type = fn_type,
778 .arg_index = 0,774 .arg_index = 0,
779 .branch_stack = &branch_stack,775 .branch_stack = &branch_stack,
780 .src_loc = src_loc,
781 .end_di_line = func.rbrace_line,776 .end_di_line = func.rbrace_line,
782 .end_di_column = func.rbrace_column,777 .end_di_column = func.rbrace_column,
783 .scope_generation = 0,778 .scope_generation = 0,
...@@ -811,10 +806,7 @@ pub fn generate(...@@ -811,10 +806,7 @@ pub fn generate(
811 );806 );
812807
813 const fn_info = zcu.typeToFunc(fn_type).?;808 const fn_info = zcu.typeToFunc(fn_type).?;
814 var call_info = function.resolveCallingConventionValues(fn_info, &.{}) catch |err| switch (err) {809 var call_info = try function.resolveCallingConventionValues(fn_info, &.{});
815 error.CodegenFail => |e| return e,
816 else => |e| return e,
817 };
818810
819 defer call_info.deinit(&function);811 defer call_info.deinit(&function);
820812
...@@ -841,7 +833,6 @@ pub fn generate(...@@ -841,7 +833,6 @@ pub fn generate(
841 }));833 }));
842834
843 function.gen() catch |err| switch (err) {835 function.gen() catch |err| switch (err) {
844 error.CodegenFail => |e| return e,
845 error.OutOfRegisters => return function.fail("ran out of registers (Zig compiler bug)", .{}),836 error.OutOfRegisters => return function.fail("ran out of registers (Zig compiler bug)", .{}),
846 else => |e| return e,837 else => |e| return e,
847 };838 };
...@@ -857,12 +848,11 @@ pub fn generate(...@@ -857,12 +848,11 @@ pub fn generate(
857pub fn generateLazy(848pub fn generateLazy(
858 bin_file: *link.File,849 bin_file: *link.File,
859 pt: Zcu.PerThread,850 pt: Zcu.PerThread,
860 src_loc: Zcu.LazySrcLoc,
861 lazy_sym: link.File.LazySymbol,851 lazy_sym: link.File.LazySymbol,
862 atom_index: link.File.AtomId,852 atom_index: link.File.AtomId,
863 w: *std.Io.Writer,853 w: *std.Io.Writer,
864 debug_output: link.File.DebugInfoOutput,854 debug_output: link.File.DebugInfoOutput,
865) (CodeGenError || std.Io.Writer.Error)!void {855) (codegen.Error || std.Io.Writer.Error)!void {
866 _ = atom_index;856 _ = atom_index;
867 const comp = bin_file.comp;857 const comp = bin_file.comp;
868 const gpa = comp.gpa;858 const gpa = comp.gpa;
...@@ -883,7 +873,6 @@ pub fn generateLazy(...@@ -883,7 +873,6 @@ pub fn generateLazy(
883 .fn_type = undefined,873 .fn_type = undefined,
884 .arg_index = 0,874 .arg_index = 0,
885 .branch_stack = undefined,875 .branch_stack = undefined,
886 .src_loc = src_loc,
887 .end_di_line = undefined,876 .end_di_line = undefined,
888 .end_di_column = undefined,877 .end_di_column = undefined,
889 .scope_generation = 0,878 .scope_generation = 0,
...@@ -893,7 +882,6 @@ pub fn generateLazy(...@@ -893,7 +882,6 @@ pub fn generateLazy(
893 defer function.mir_instructions.deinit(gpa);882 defer function.mir_instructions.deinit(gpa);
894883
895 function.genLazy(lazy_sym) catch |err| switch (err) {884 function.genLazy(lazy_sym) catch |err| switch (err) {
896 error.CodegenFail => |e| return e,
897 error.OutOfRegisters => return function.fail("ran out of registers (Zig compiler bug)", .{}),885 error.OutOfRegisters => return function.fail("ran out of registers (Zig compiler bug)", .{}),
898 else => |e| return e,886 else => |e| return e,
899 };887 };
...@@ -910,7 +898,7 @@ pub fn generateLazy(...@@ -910,7 +898,7 @@ pub fn generateLazy(
910 .allocator = gpa,898 .allocator = gpa,
911 .mir = mir,899 .mir = mir,
912 .cc = .auto,900 .cc = .auto,
913 .src_loc = src_loc,901 .src_loc = Type.fromInterned(lazy_sym.ty).srcLocOrNull(pt.zcu) orelse .unneeded,
914 .output_mode = comp.config.output_mode,902 .output_mode = comp.config.output_mode,
915 .link_mode = comp.config.link_mode,903 .link_mode = comp.config.link_mode,
916 .pic = mod.pic,904 .pic = mod.pic,
...@@ -946,7 +934,10 @@ fn formatWipMir(data: FormatWipMirData, writer: *std.Io.Writer) std.Io.Writer.Er...@@ -946,7 +934,10 @@ fn formatWipMir(data: FormatWipMirData, writer: *std.Io.Writer) std.Io.Writer.Er
946 .frame_locs = data.func.frame_locs.slice(),934 .frame_locs = data.func.frame_locs.slice(),
947 },935 },
948 .cc = .auto,936 .cc = .auto,
949 .src_loc = data.func.src_loc,937 .src_loc = switch (data.func.owner) {
938 .nav_index => |nav| pt.zcu.navSrcLoc(nav),
939 .lazy_sym => |lazy_sym| Type.fromInterned(lazy_sym.ty).srcLocOrNull(pt.zcu) orelse .unneeded,
940 },
950 .output_mode = comp.config.output_mode,941 .output_mode = comp.config.output_mode,
951 .link_mode = comp.config.link_mode,942 .link_mode = comp.config.link_mode,
952 .pic = comp.root_mod.pic,943 .pic = comp.root_mod.pic,
...@@ -8144,28 +8135,21 @@ fn genTypedValue(func: *Func, val: Value) InnerError!MCValue {...@@ -8144,28 +8135,21 @@ fn genTypedValue(func: *Func, val: Value) InnerError!MCValue {
8144 const pt = func.pt;8135 const pt = func.pt;
81458136
8146 const lf = func.bin_file;8137 const lf = func.bin_file;
8147 const src_loc = func.src_loc;
81488138
8149 const result: codegen.GenResult = if (val.isUndef(pt.zcu))8139 const result: codegen.MCValue = if (val.isUndef(pt.zcu))
8150 switch (try lf.lowerUav(pt, val.toIntern(), .none, src_loc)) {8140 .{ .load_symbol = try lf.lowerUav(pt, val.toIntern(), .none) }
8151 .sym_index => |sym_index| .{ .mcv = .{ .load_symbol = sym_index } },
8152 .fail => |em| .{ .fail = em },
8153 }
8154 else8141 else
8155 try codegen.genTypedValue(lf, pt, src_loc, val, func.target);8142 try codegen.genTypedValue(lf, pt, val, func.target);
8156 const mcv: MCValue = switch (result) {8143 const mcv: MCValue = switch (result) {
8157 .mcv => |mcv| switch (mcv) {8144 .none => .none,
8158 .none => .none,8145 .undef => unreachable,
8159 .undef => unreachable,8146 .lea_symbol => |sym_index| .{ .lea_symbol = .{ .sym = sym_index } },
8160 .lea_symbol => |sym_index| .{ .lea_symbol = .{ .sym = sym_index } },8147 .load_symbol => |sym_index| .{ .load_symbol = .{ .sym = sym_index } },
8161 .load_symbol => |sym_index| .{ .load_symbol = .{ .sym = sym_index } },8148 .immediate => |imm| .{ .immediate = imm },
8162 .immediate => |imm| .{ .immediate = imm },8149 .memory => |addr| .{ .memory = addr },
8163 .memory => |addr| .{ .memory = addr },8150 .load_got, .load_direct, .lea_direct => {
8164 .load_got, .load_direct, .lea_direct => {8151 return func.fail("TODO: genTypedValue {s}", .{@tagName(result)});
8165 return func.fail("TODO: genTypedValue {s}", .{@tagName(mcv)});
8166 },
8167 },8152 },
8168 .fail => |msg| return func.failMsg(msg),
8169 };8153 };
8170 return mcv;8154 return mcv;
8171}8155}
...@@ -8353,24 +8337,24 @@ fn wantSafety(func: *Func) bool {...@@ -8353,24 +8337,24 @@ fn wantSafety(func: *Func) bool {
8353 };8337 };
8354}8338}
83558339
8356fn fail(func: *const Func, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {8340fn fail(func: *const Func, comptime format: []const u8, args: anytype) error{ OutOfMemory, AlreadyReported } {
8357 @branchHint(.cold);8341 @branchHint(.cold);
8358 const zcu = func.pt.zcu;8342 const zcu = func.pt.zcu;
8359 switch (func.owner) {8343 switch (func.owner) {
8360 .nav_index => |i| return zcu.codegenFail(i, format, args),8344 .nav_index => |i| return zcu.codegenFail(i, format, args),
8361 .lazy_sym => |s| return zcu.codegenFailType(s.ty, format, args),8345 .lazy_sym => |s| return zcu.codegenFailType(s.ty, format, args),
8362 }8346 }
8363 return error.CodegenFail;8347 return error.AlreadyReported;
8364}8348}
83658349
8366fn failMsg(func: *const Func, msg: *ErrorMsg) error{ OutOfMemory, CodegenFail } {8350fn failMsg(func: *const Func, msg: *ErrorMsg) error{ OutOfMemory, AlreadyReported } {
8367 @branchHint(.cold);8351 @branchHint(.cold);
8368 const zcu = func.pt.zcu;8352 const zcu = func.pt.zcu;
8369 switch (func.owner) {8353 switch (func.owner) {
8370 .nav_index => |i| return zcu.codegenFailMsg(i, msg),8354 .nav_index => |i| return zcu.codegenFailMsg(i, msg),
8371 .lazy_sym => |s| return zcu.codegenFailTypeMsg(s.ty, msg),8355 .lazy_sym => |s| return zcu.codegenFailTypeMsg(s.ty, msg),
8372 }8356 }
8373 return error.CodegenFail;8357 return error.AlreadyReported;
8374}8358}
83758359
8376fn parseRegName(name: []const u8) ?Register {8360fn parseRegName(name: []const u8) ?Register {
src/codegen/riscv64/Mir.zig+2-3
...@@ -107,12 +107,11 @@ pub fn emit(...@@ -107,12 +107,11 @@ pub fn emit(
107 mir: Mir,107 mir: Mir,
108 lf: *link.File,108 lf: *link.File,
109 pt: Zcu.PerThread,109 pt: Zcu.PerThread,
110 src_loc: Zcu.LazySrcLoc,
111 func_index: InternPool.Index,110 func_index: InternPool.Index,
112 atom_index: link.File.AtomId,111 atom_index: link.File.AtomId,
113 w: *std.Io.Writer,112 w: *std.Io.Writer,
114 debug_output: link.File.DebugInfoOutput,113 debug_output: link.File.DebugInfoOutput,
115) (codegen.CodeGenError || std.Io.Writer.Error)!void {114) (codegen.Error || std.Io.Writer.Error)!void {
116 _ = atom_index;115 _ = atom_index;
117 const zcu = pt.zcu;116 const zcu = pt.zcu;
118 const comp = zcu.comp;117 const comp = zcu.comp;
...@@ -127,7 +126,7 @@ pub fn emit(...@@ -127,7 +126,7 @@ pub fn emit(
127 .allocator = gpa,126 .allocator = gpa,
128 .mir = mir,127 .mir = mir,
129 .cc = fn_info.cc,128 .cc = fn_info.cc,
130 .src_loc = src_loc,129 .src_loc = zcu.navSrcLoc(nav),
131 .output_mode = comp.config.output_mode,130 .output_mode = comp.config.output_mode,
132 .link_mode = comp.config.link_mode,131 .link_mode = comp.config.link_mode,
133 .pic = mod.pic,132 .pic = mod.pic,
src/codegen/sparc64/CodeGen.zig+11-28
...@@ -19,7 +19,6 @@ const Air = @import("../../Air.zig");...@@ -19,7 +19,6 @@ const Air = @import("../../Air.zig");
19const Mir = @import("Mir.zig");19const Mir = @import("Mir.zig");
20const Emit = @import("Emit.zig");20const Emit = @import("Emit.zig");
21const Type = @import("../../Type.zig");21const Type = @import("../../Type.zig");
22const CodeGenError = codegen.CodeGenError;
23const Endian = std.lang.Endian;22const Endian = std.lang.Endian;
24const Alignment = InternPool.Alignment;23const Alignment = InternPool.Alignment;
2524
...@@ -39,7 +38,7 @@ const gp = abi.RegisterClass.gp;...@@ -39,7 +38,7 @@ const gp = abi.RegisterClass.gp;
3938
40const Self = @This();39const Self = @This();
4140
42const InnerError = CodeGenError || error{OutOfRegisters};41const InnerError = codegen.Error || error{OutOfRegisters};
4342
44pub fn legalizeFeatures(_: *const std.Target) ?*const Air.Legalize.Features {43pub fn legalizeFeatures(_: *const std.Target) ?*const Air.Legalize.Features {
45 return null;44 return null;
...@@ -57,12 +56,10 @@ liveness: Air.Liveness,...@@ -57,12 +56,10 @@ liveness: Air.Liveness,
57bin_file: *link.File,56bin_file: *link.File,
58target: *const std.Target,57target: *const std.Target,
59func_index: InternPool.Index,58func_index: InternPool.Index,
60err_msg: ?*ErrorMsg,
61args: []MCValue,59args: []MCValue,
62ret_mcv: MCValue,60ret_mcv: MCValue,
63fn_type: Type,61fn_type: Type,
64arg_index: usize,62arg_index: usize,
65src_loc: Zcu.LazySrcLoc,
66stack_align: Alignment,63stack_align: Alignment,
6764
68/// MIR Instructions65/// MIR Instructions
...@@ -264,11 +261,10 @@ const BigTomb = struct {...@@ -264,11 +261,10 @@ const BigTomb = struct {
264pub fn generate(261pub fn generate(
265 lf: *link.File,262 lf: *link.File,
266 pt: Zcu.PerThread,263 pt: Zcu.PerThread,
267 src_loc: Zcu.LazySrcLoc,
268 func_index: InternPool.Index,264 func_index: InternPool.Index,
269 air: *const Air,265 air: *const Air,
270 liveness: *const ?Air.Liveness,266 liveness: *const ?Air.Liveness,
271) CodeGenError!Mir {267) codegen.Error!Mir {
272 const zcu = pt.zcu;268 const zcu = pt.zcu;
273 const gpa = zcu.gpa;269 const gpa = zcu.gpa;
274 const func = zcu.funcInfo(func_index);270 const func = zcu.funcInfo(func_index);
...@@ -292,13 +288,11 @@ pub fn generate(...@@ -292,13 +288,11 @@ pub fn generate(
292 .target = target,288 .target = target,
293 .bin_file = lf,289 .bin_file = lf,
294 .func_index = func_index,290 .func_index = func_index,
295 .err_msg = null,
296 .args = undefined, // populated after `resolveCallingConventionValues`291 .args = undefined, // populated after `resolveCallingConventionValues`
297 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`292 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
298 .fn_type = func_ty,293 .fn_type = func_ty,
299 .arg_index = 0,294 .arg_index = 0,
300 .branch_stack = &branch_stack,295 .branch_stack = &branch_stack,
301 .src_loc = src_loc,
302 .stack_align = undefined,296 .stack_align = undefined,
303 .end_di_line = func.rbrace_line,297 .end_di_line = func.rbrace_line,
304 .end_di_column = func.rbrace_column,298 .end_di_column = func.rbrace_column,
...@@ -307,10 +301,7 @@ pub fn generate(...@@ -307,10 +301,7 @@ pub fn generate(
307 defer function.blocks.deinit(gpa);301 defer function.blocks.deinit(gpa);
308 defer function.exitlude_jump_relocs.deinit(gpa);302 defer function.exitlude_jump_relocs.deinit(gpa);
309303
310 var call_info = function.resolveCallingConventionValues(func_ty, .callee) catch |err| switch (err) {304 var call_info = try function.resolveCallingConventionValues(func_ty, .callee);
311 error.CodegenFail => |e| return e,
312 else => |e| return e,
313 };
314 defer call_info.deinit(&function);305 defer call_info.deinit(&function);
315306
316 function.args = call_info.args;307 function.args = call_info.args;
...@@ -319,7 +310,6 @@ pub fn generate(...@@ -319,7 +310,6 @@ pub fn generate(
319 function.max_end_stack = call_info.stack_byte_count;310 function.max_end_stack = call_info.stack_byte_count;
320311
321 function.gen() catch |err| switch (err) {312 function.gen() catch |err| switch (err) {
322 error.CodegenFail => |e| return e,
323 error.OutOfRegisters => return function.fail("ran out of registers (Zig compiler bug)", .{}),313 error.OutOfRegisters => return function.fail("ran out of registers (Zig compiler bug)", .{}),
324 else => |e| return e,314 else => |e| return e,
325 };315 };
...@@ -3446,15 +3436,15 @@ fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type)...@@ -3446,15 +3436,15 @@ fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type)
3446 }3436 }
3447}3437}
34483438
3449fn fail(self: *Self, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {3439fn fail(self: *Self, comptime format: []const u8, args: anytype) error{ OutOfMemory, AlreadyReported } {
3450 @branchHint(.cold);3440 @branchHint(.cold);
3451 const zcu = self.pt.zcu;3441 const zcu = self.pt.zcu;
3452 const func = zcu.funcInfo(self.func_index);3442 const func = zcu.funcInfo(self.func_index);
3453 const msg = try ErrorMsg.create(zcu.gpa, self.src_loc, format, args);3443 const msg = try ErrorMsg.create(zcu.gpa, zcu.navSrcLoc(func.owner_nav), format, args);
3454 return zcu.codegenFailMsg(func.owner_nav, msg);3444 return zcu.codegenFailMsg(func.owner_nav, msg);
3455}3445}
34563446
3457fn failMsg(self: *Self, msg: *ErrorMsg) error{ OutOfMemory, CodegenFail } {3447fn failMsg(self: *Self, msg: *ErrorMsg) error{ OutOfMemory, AlreadyReported } {
3458 @branchHint(.cold);3448 @branchHint(.cold);
3459 const zcu = self.pt.zcu;3449 const zcu = self.pt.zcu;
3460 const func = zcu.funcInfo(self.func_index);3450 const func = zcu.funcInfo(self.func_index);
...@@ -4036,21 +4026,14 @@ fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {...@@ -4036,21 +4026,14 @@ fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {
4036 const mcv: MCValue = switch (try codegen.genTypedValue(4026 const mcv: MCValue = switch (try codegen.genTypedValue(
4037 self.bin_file,4027 self.bin_file,
4038 pt,4028 pt,
4039 self.src_loc,
4040 val,4029 val,
4041 self.target,4030 self.target,
4042 )) {4031 )) {
4043 .mcv => |mcv| switch (mcv) {4032 .none => .none,
4044 .none => .none,4033 .undef => .undef,
4045 .undef => .undef,4034 .load_got, .load_symbol, .load_direct, .lea_symbol, .lea_direct => unreachable, // TODO
4046 .load_got, .load_symbol, .load_direct, .lea_symbol, .lea_direct => unreachable, // TODO4035 .immediate => |imm| .{ .immediate = imm },
4047 .immediate => |imm| .{ .immediate = imm },4036 .memory => |addr| .{ .memory = addr },
4048 .memory => |addr| .{ .memory = addr },
4049 },
4050 .fail => |msg| {
4051 self.err_msg = msg;
4052 return error.CodegenFail;
4053 },
4054 };4037 };
4055 return mcv;4038 return mcv;
4056}4039}
src/codegen/sparc64/Mir.zig+2-3
...@@ -378,12 +378,11 @@ pub fn emit(...@@ -378,12 +378,11 @@ pub fn emit(
378 mir: Mir,378 mir: Mir,
379 lf: *link.File,379 lf: *link.File,
380 pt: Zcu.PerThread,380 pt: Zcu.PerThread,
381 src_loc: Zcu.LazySrcLoc,
382 func_index: InternPool.Index,381 func_index: InternPool.Index,
383 atom_index: link.File.AtomId,382 atom_index: link.File.AtomId,
384 w: *std.Io.Writer,383 w: *std.Io.Writer,
385 debug_output: link.File.DebugInfoOutput,384 debug_output: link.File.DebugInfoOutput,
386) (codegen.CodeGenError || std.Io.Writer.Error)!void {385) (codegen.Error || std.Io.Writer.Error)!void {
387 _ = atom_index;386 _ = atom_index;
388 const zcu = pt.zcu;387 const zcu = pt.zcu;
389 const func = zcu.funcInfo(func_index);388 const func = zcu.funcInfo(func_index);
...@@ -394,7 +393,7 @@ pub fn emit(...@@ -394,7 +393,7 @@ pub fn emit(
394 .bin_file = lf,393 .bin_file = lf,
395 .debug_output = debug_output,394 .debug_output = debug_output,
396 .target = &mod.resolved_target.result,395 .target = &mod.resolved_target.result,
397 .src_loc = src_loc,396 .src_loc = zcu.navSrcLoc(nav),
398 .w = w,397 .w = w,
399 .prev_di_pc = 0,398 .prev_di_pc = 0,
400 .prev_di_line = func.lbrace_line,399 .prev_di_line = func.lbrace_line,
src/codegen/spirv/CodeGen.zig+12-16
...@@ -156,7 +156,6 @@ inst_results: std.AutoHashMapUnmanaged(Air.Inst.Index, Id) = .empty,...@@ -156,7 +156,6 @@ inst_results: std.AutoHashMapUnmanaged(Air.Inst.Index, Id) = .empty,
156id_scratch: std.ArrayList(Id) = .empty,156id_scratch: std.ArrayList(Id) = .empty,
157prologue: Section = .{},157prologue: Section = .{},
158body: Section = .{},158body: Section = .{},
159error_msg: ?*Zcu.ErrorMsg = null,
160159
161pub fn deinit(cg: *CodeGen) void {160pub fn deinit(cg: *CodeGen) void {
162 const gpa = cg.module.gpa;161 const gpa = cg.module.gpa;
...@@ -168,7 +167,7 @@ pub fn deinit(cg: *CodeGen) void {...@@ -168,7 +167,7 @@ pub fn deinit(cg: *CodeGen) void {
168 cg.body.deinit(gpa);167 cg.body.deinit(gpa);
169}168}
170169
171const Error = error{ CodegenFail, OutOfMemory };170const Error = error{ AlreadyReported, OutOfMemory };
172171
173pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void {172pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void {
174 const gpa = cg.module.gpa;173 const gpa = cg.module.gpa;
...@@ -363,11 +362,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void {...@@ -363,11 +362,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void {
363362
364pub fn fail(cg: *CodeGen, comptime format: []const u8, args: anytype) Error {363pub fn fail(cg: *CodeGen, comptime format: []const u8, args: anytype) Error {
365 @branchHint(.cold);364 @branchHint(.cold);
366 const zcu = cg.module.zcu;365 return cg.module.zcu.codegenFail(cg.owner_nav, format, args);
367 const src_loc = zcu.navSrcLoc(cg.owner_nav);
368 assert(cg.error_msg == null);
369 cg.error_msg = try Zcu.ErrorMsg.create(zcu.gpa, src_loc, format, args);
370 return error.CodegenFail;
371}366}
372367
373pub fn todo(cg: *CodeGen, comptime format: []const u8, args: anytype) Error {368pub fn todo(cg: *CodeGen, comptime format: []const u8, args: anytype) Error {
...@@ -5934,14 +5929,14 @@ fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) !?Id {...@@ -5934,14 +5929,14 @@ fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
5934 // them as notes here.5929 // them as notes here.
5935 // TODO: Translate proper error locations.5930 // TODO: Translate proper error locations.
5936 assert(ass.errors.items.len != 0);5931 assert(ass.errors.items.len != 0);
5937 assert(cg.error_msg == null);5932 const msg: *Zcu.ErrorMsg = msg: {
5938 const src_loc = zcu.navSrcLoc(cg.owner_nav);5933 const src_loc = zcu.navSrcLoc(cg.owner_nav);
5939 cg.error_msg = try Zcu.ErrorMsg.create(zcu.gpa, src_loc, "failed to assemble SPIR-V inline assembly", .{});5934 var msg: *Zcu.ErrorMsg = try .create(zcu.gpa, src_loc, "failed to assemble SPIR-V inline assembly", .{});
5940 const notes = try zcu.gpa.alloc(Zcu.ErrorMsg, ass.errors.items.len);5935 errdefer msg.destroy(zcu.gpa);
59415936
5942 // Sub-scope to prevent `return error.CodegenFail` from running the errdefers.5937 const notes = try zcu.gpa.alloc(Zcu.ErrorMsg, ass.errors.items.len);
5943 {
5944 errdefer zcu.gpa.free(notes);5938 errdefer zcu.gpa.free(notes);
5939
5945 var i: usize = 0;5940 var i: usize = 0;
5946 errdefer for (notes[0..i]) |*note| {5941 errdefer for (notes[0..i]) |*note| {
5947 note.deinit(zcu.gpa);5942 note.deinit(zcu.gpa);
...@@ -5950,9 +5945,10 @@ fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) !?Id {...@@ -5950,9 +5945,10 @@ fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
5950 while (i < ass.errors.items.len) : (i += 1) {5945 while (i < ass.errors.items.len) : (i += 1) {
5951 notes[i] = try Zcu.ErrorMsg.init(zcu.gpa, src_loc, "{s}", .{ass.errors.items[i].msg});5946 notes[i] = try Zcu.ErrorMsg.init(zcu.gpa, src_loc, "{s}", .{ass.errors.items[i].msg});
5952 }5947 }
5953 }5948
5954 cg.error_msg.?.notes = notes;5949 break :msg msg;
5955 return error.CodegenFail;5950 };
5951 return zcu.codegenFailMsg(cg.owner_nav, msg);
5956 },5952 },
5957 else => |others| return others,5953 else => |others| return others,
5958 };5954 };
src/codegen/wasm/CodeGen.zig+4-9
...@@ -329,7 +329,7 @@ const bookkeeping_init = if (std.debug.runtime_safety) @as(usize, 0) else {};...@@ -329,7 +329,7 @@ const bookkeeping_init = if (std.debug.runtime_safety) @as(usize, 0) else {};
329const InnerError = error{329const InnerError = error{
330 OutOfMemory,330 OutOfMemory,
331 /// An error occurred when trying to lower AIR to MIR.331 /// An error occurred when trying to lower AIR to MIR.
332 CodegenFail,332 AlreadyReported,
333 /// Compiler implementation could not handle a large integer.333 /// Compiler implementation could not handle a large integer.
334 Overflow,334 Overflow,
335} || link.File.UpdateDebugInfoError;335} || link.File.UpdateDebugInfoError;
...@@ -355,7 +355,7 @@ pub fn deinit(cg: *CodeGen) void {...@@ -355,7 +355,7 @@ pub fn deinit(cg: *CodeGen) void {
355 cg.* = undefined;355 cg.* = undefined;
356}356}
357357
358pub fn fail(cg: *CodeGen, comptime fmt: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {358pub fn fail(cg: *CodeGen, comptime fmt: []const u8, args: anytype) error{ OutOfMemory, AlreadyReported } {
359 const zcu = cg.pt.zcu;359 const zcu = cg.pt.zcu;
360 const func = zcu.funcInfo(cg.func_index);360 const func = zcu.funcInfo(cg.func_index);
361 return zcu.codegenFail(func.owner_nav, fmt, args);361 return zcu.codegenFail(func.owner_nav, fmt, args);
...@@ -756,21 +756,17 @@ fn ensureAllocLocal(cg: *CodeGen, ty: Type) InnerError!WValue {...@@ -756,21 +756,17 @@ fn ensureAllocLocal(cg: *CodeGen, ty: Type) InnerError!WValue {
756756
757pub const Error = error{757pub const Error = error{
758 OutOfMemory,758 OutOfMemory,
759 /// Compiler was asked to operate on a number larger than supported.
760 Overflow,
761 /// Indicates the error is already stored in Zcu `failed_codegen`.759 /// Indicates the error is already stored in Zcu `failed_codegen`.
762 CodegenFail,760 AlreadyReported,
763};761};
764762
765pub fn generate(763pub fn generate(
766 bin_file: *link.File,764 bin_file: *link.File,
767 pt: Zcu.PerThread,765 pt: Zcu.PerThread,
768 src_loc: Zcu.LazySrcLoc,
769 func_index: InternPool.Index,766 func_index: InternPool.Index,
770 air: *const Air,767 air: *const Air,
771 liveness: *const ?Air.Liveness,768 liveness: *const ?Air.Liveness,
772) Error!Mir {769) Error!Mir {
773 _ = src_loc;
774 _ = bin_file;770 _ = bin_file;
775 const zcu = pt.zcu;771 const zcu = pt.zcu;
776 const gpa = zcu.gpa;772 const gpa = zcu.gpa;
...@@ -814,9 +810,8 @@ pub fn generate(...@@ -814,9 +810,8 @@ pub fn generate(
814 try code_gen.mir_func_tys.putNoClobber(gpa, fn_ty.toIntern(), {});810 try code_gen.mir_func_tys.putNoClobber(gpa, fn_ty.toIntern(), {});
815811
816 return generateInner(&code_gen, any_returns) catch |err| switch (err) {812 return generateInner(&code_gen, any_returns) catch |err| switch (err) {
817 error.CodegenFail,813 error.AlreadyReported,
818 error.OutOfMemory,814 error.OutOfMemory,
819 error.Overflow,
820 => |e| return e,815 => |e| return e,
821 else => |e| return code_gen.fail("failed to generate function: {s}", .{@errorName(e)}),816 else => |e| return code_gen.fail("failed to generate function: {s}", .{@errorName(e)}),
822 };817 };
src/codegen/x86_64/CodeGen.zig+10-17
...@@ -31,7 +31,7 @@ const RegisterManager = abi.RegisterManager;...@@ -31,7 +31,7 @@ const RegisterManager = abi.RegisterManager;
31const RegisterLock = RegisterManager.RegisterLock;31const RegisterLock = RegisterManager.RegisterLock;
32const FrameIndex = bits.FrameIndex;32const FrameIndex = bits.FrameIndex;
3333
34const InnerError = codegen.CodeGenError || error{OutOfRegisters};34const InnerError = codegen.Error || error{OutOfRegisters};
3535
36pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {36pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
37 return comptime &.initMany(&.{37 return comptime &.initMany(&.{
...@@ -106,7 +106,6 @@ va_info: union {...@@ -106,7 +106,6 @@ va_info: union {
106ret_mcv: InstTracking,106ret_mcv: InstTracking,
107err_ret_trace_reg: Register,107err_ret_trace_reg: Register,
108fn_type: Type,108fn_type: Type,
109src_loc: Zcu.LazySrcLoc,
110109
111eflags_inst: ?Air.Inst.Index = null,110eflags_inst: ?Air.Inst.Index = null,
112111
...@@ -869,11 +868,10 @@ const CodeGen = @This();...@@ -869,11 +868,10 @@ const CodeGen = @This();
869pub fn generate(868pub fn generate(
870 bin_file: *link.File,869 bin_file: *link.File,
871 pt: Zcu.PerThread,870 pt: Zcu.PerThread,
872 src_loc: Zcu.LazySrcLoc,
873 func_index: InternPool.Index,871 func_index: InternPool.Index,
874 air: *const Air,872 air: *const Air,
875 liveness: *const ?Air.Liveness,873 liveness: *const ?Air.Liveness,
876) codegen.CodeGenError!Mir {874) codegen.Error!Mir {
877 _ = bin_file;875 _ = bin_file;
878 const zcu = pt.zcu;876 const zcu = pt.zcu;
879 const gpa = zcu.gpa;877 const gpa = zcu.gpa;
...@@ -898,7 +896,6 @@ pub fn generate(...@@ -898,7 +896,6 @@ pub fn generate(
898 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`896 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
899 .err_ret_trace_reg = undefined, // populated after `resolveCallingConventionValues`897 .err_ret_trace_reg = undefined, // populated after `resolveCallingConventionValues`
900 .fn_type = fn_type,898 .fn_type = fn_type,
901 .src_loc = src_loc,
902 };899 };
903 defer {900 defer {
904 function.frame_allocs.deinit(gpa);901 function.frame_allocs.deinit(gpa);
...@@ -937,10 +934,7 @@ pub fn generate(...@@ -937,10 +934,7 @@ pub fn generate(
937 );934 );
938935
939 const fn_info = zcu.typeToFunc(fn_type).?;936 const fn_info = zcu.typeToFunc(fn_type).?;
940 var call_info = function.resolveCallingConventionValues(fn_info, &.{}, .args_frame) catch |err| switch (err) {937 var call_info = try function.resolveCallingConventionValues(fn_info, &.{}, .args_frame);
941 error.CodegenFail => |e| return e,
942 else => |e| return e,
943 };
944 defer call_info.deinit(&function);938 defer call_info.deinit(&function);
945939
946 function.args = call_info.args;940 function.args = call_info.args;
...@@ -983,7 +977,6 @@ pub fn generate(...@@ -983,7 +977,6 @@ pub fn generate(
983 }977 }
984978
985 function.gen(&file.zir.?, func_zir.inst, func.comptime_args, call_info.air_arg_count) catch |err| switch (err) {979 function.gen(&file.zir.?, func_zir.inst, func.comptime_args, call_info.air_arg_count) catch |err| switch (err) {
986 error.CodegenFail => |e| return e,
987 error.OutOfRegisters => return function.fail("ran out of registers (Zig compiler bug)", .{}),980 error.OutOfRegisters => return function.fail("ran out of registers (Zig compiler bug)", .{}),
988 else => |e| return e,981 else => |e| return e,
989 };982 };
...@@ -1027,12 +1020,11 @@ pub fn getTmpMir(cg: *CodeGen) Mir {...@@ -1027,12 +1020,11 @@ pub fn getTmpMir(cg: *CodeGen) Mir {
1027pub fn generateLazy(1020pub fn generateLazy(
1028 bin_file: *link.File,1021 bin_file: *link.File,
1029 pt: Zcu.PerThread,1022 pt: Zcu.PerThread,
1030 src_loc: Zcu.LazySrcLoc,
1031 lazy_sym: link.File.LazySymbol,1023 lazy_sym: link.File.LazySymbol,
1032 atom_id: link.File.AtomId,1024 atom_id: link.File.AtomId,
1033 w: *std.Io.Writer,1025 w: *std.Io.Writer,
1034 debug_output: link.File.DebugInfoOutput,1026 debug_output: link.File.DebugInfoOutput,
1035) codegen.CodeGenError!void {1027) codegen.Error!void {
1036 const gpa = pt.zcu.gpa;1028 const gpa = pt.zcu.gpa;
1037 // This function is for generating global code, so we use the root module.1029 // This function is for generating global code, so we use the root module.
1038 const mod = pt.zcu.comp.root_mod;1030 const mod = pt.zcu.comp.root_mod;
...@@ -1050,7 +1042,6 @@ pub fn generateLazy(...@@ -1050,7 +1042,6 @@ pub fn generateLazy(
1050 .ret_mcv = undefined,1042 .ret_mcv = undefined,
1051 .err_ret_trace_reg = undefined,1043 .err_ret_trace_reg = undefined,
1052 .fn_type = undefined,1044 .fn_type = undefined,
1053 .src_loc = src_loc,
1054 };1045 };
1055 defer {1046 defer {
1056 function.inst_tracking.deinit(gpa);1047 function.inst_tracking.deinit(gpa);
...@@ -1068,12 +1059,11 @@ pub fn generateLazy(...@@ -1068,12 +1059,11 @@ pub fn generateLazy(
1068 }1059 }
10691060
1070 function.genLazy(lazy_sym) catch |err| switch (err) {1061 function.genLazy(lazy_sym) catch |err| switch (err) {
1071 error.CodegenFail => |e| return e,
1072 error.OutOfRegisters => return function.fail("ran out of registers (Zig compiler bug)", .{}),1062 error.OutOfRegisters => return function.fail("ran out of registers (Zig compiler bug)", .{}),
1073 else => |e| return e,1063 else => |e| return e,
1074 };1064 };
10751065
1076 try function.getTmpMir().emitLazy(bin_file, pt, src_loc, lazy_sym, atom_id, w, debug_output);1066 try function.getTmpMir().emitLazy(bin_file, pt, lazy_sym, atom_id, w, debug_output);
1077}1067}
10781068
1079const FormatNavData = struct {1069const FormatNavData = struct {
...@@ -1111,7 +1101,10 @@ fn formatWipMir(data: FormatWipMirData, w: *Writer) Writer.Error!void {...@@ -1111,7 +1101,10 @@ fn formatWipMir(data: FormatWipMirData, w: *Writer) Writer.Error!void {
1111 .allocator = data.self.gpa,1101 .allocator = data.self.gpa,
1112 .mir = data.self.getTmpMir(),1102 .mir = data.self.getTmpMir(),
1113 .cc = .auto,1103 .cc = .auto,
1114 .src_loc = data.self.src_loc,1104 .src_loc = switch (data.self.owner) {
1105 .nav_index => |nav| data.self.pt.zcu.navSrcLoc(nav),
1106 .lazy_sym => |lazy_sym| Type.fromInterned(lazy_sym.ty).srcLocOrNull(data.self.pt.zcu) orelse .unneeded,
1107 },
1115 };1108 };
1116 var first = true;1109 var first = true;
1117 for ((lower.lowerMir(data.inst) catch |err| switch (err) {1110 for ((lower.lowerMir(data.inst) catch |err| switch (err) {
...@@ -181508,7 +181501,7 @@ fn resolveCallingConventionValues(...@@ -181508,7 +181501,7 @@ fn resolveCallingConventionValues(
181508 return result;181501 return result;
181509}181502}
181510181503
181511fn fail(cg: *CodeGen, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {181504fn fail(cg: *CodeGen, comptime format: []const u8, args: anytype) error{ OutOfMemory, AlreadyReported } {
181512 @branchHint(.cold);181505 @branchHint(.cold);
181513 const zcu = cg.pt.zcu;181506 const zcu = cg.pt.zcu;
181514 return switch (cg.owner) {181507 return switch (cg.owner) {
src/codegen/x86_64/Emit.zig+13-57
...@@ -17,6 +17,7 @@ relocs: std.ArrayList(Reloc),...@@ -17,6 +17,7 @@ relocs: std.ArrayList(Reloc),
17table_relocs: std.ArrayList(TableReloc),17table_relocs: std.ArrayList(TableReloc),
1818
19pub const Error = Lower.Error || error{19pub const Error = Lower.Error || error{
20 AlreadyReported,
20 EmitFail,21 EmitFail,
21 NotFile,22 NotFile,
22} || std.posix.MMapError || std.posix.MRemapError || link.File.UpdateDebugInfoError;23} || std.posix.MMapError || std.posix.MRemapError || link.File.UpdateDebugInfoError;
...@@ -101,20 +102,11 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -101,20 +102,11 @@ pub fn emitMir(emit: *Emit) Error!void {
101 .inst => |inst| .{ .inst = inst },102 .inst => |inst| .{ .inst = inst },
102 .table => .table,103 .table => .table,
103 .nav => |nav| {104 .nav => |nav| {
104 const symbol_id = switch (try codegen.genNavRef(105 const symbol_id = try codegen.genNavRef(
105 emit.bin_file,106 emit.bin_file,
106 emit.pt,107 emit.pt,
107 emit.lower.src_loc,
108 nav,108 nav,
109 emit.lower.target,109 );
110 )) {
111 .sym_index => |symbol_id| symbol_id,
112 .fail => |em| {
113 assert(emit.lower.err_msg == null);
114 emit.lower.err_msg = em;
115 return error.EmitFail;
116 },
117 };
118 const target_symbol: RelocInfo.Target.Symbol = if (ip.getNav(nav).getExtern(ip)) |@"extern"| .{110 const target_symbol: RelocInfo.Target.Symbol = if (ip.getNav(nav).getExtern(ip)) |@"extern"| .{
119 .symbol = symbol_id,111 .symbol = symbol_id,
120 .is_extern = switch (@"extern".visibility) {112 .is_extern = switch (@"extern".visibility) {
...@@ -133,19 +125,11 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -133,19 +125,11 @@ pub fn emitMir(emit: *Emit) Error!void {
133 }125 }
134 },126 },
135 .uav => |uav| .{ .symbol = .{127 .uav => |uav| .{ .symbol = .{
136 .symbol = switch (try emit.bin_file.lowerUav(128 .symbol = try emit.bin_file.lowerUav(
137 emit.pt,129 emit.pt,
138 uav.val,130 uav.val,
139 Type.fromInterned(uav.orig_ty).ptrAlignment(emit.pt.zcu),131 Type.fromInterned(uav.orig_ty).ptrAlignment(emit.pt.zcu),
140 emit.lower.src_loc,132 ),
141 )) {
142 .sym_index => |symbol_id| symbol_id,
143 .fail => |em| {
144 assert(emit.lower.err_msg == null);
145 emit.lower.err_msg = em;
146 return error.EmitFail;
147 },
148 },
149 .is_extern = false,133 .is_extern = false,
150 } },134 } },
151 .lazy_sym => |lazy_sym| .{ .symbol = .{135 .lazy_sym => |lazy_sym| .{ .symbol = .{
...@@ -168,17 +152,14 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -168,17 +152,14 @@ pub fn emitMir(emit: *Emit) Error!void {
168 .extern_func => |extern_func| .{ .symbol = .{152 .extern_func => |extern_func| .{ .symbol = .{
169 .symbol = if (emit.bin_file.cast(.elf)) |elf_file|153 .symbol = if (emit.bin_file.cast(.elf)) |elf_file|
170 @enumFromInt(try elf_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, null))154 @enumFromInt(try elf_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, null))
171 else if (emit.bin_file.cast(.elf2)) |elf| elf.externSymbol(.{155 else if (emit.bin_file.cast(.elf2)) |elf| try elf.externSymbol(.{
172 .name = extern_func.toSlice(&emit.lower.mir).?,156 .name = extern_func.toSlice(&emit.lower.mir).?,
173 .lib_name = switch (comp.compiler_rt_strat) {157 .lib_name = switch (comp.compiler_rt_strat) {
174 .none, .lib, .obj, .zcu => null,158 .none, .lib, .obj, .zcu => null,
175 .dyn_lib => "compiler_rt",159 .dyn_lib => "compiler_rt",
176 },160 },
177 .type = .FUNC,161 .type = .FUNC,
178 }) catch |err| switch (err) {162 }) else if (emit.bin_file.cast(.macho)) |macho_file|
179 error.LinkOnceUnsupported => unreachable,
180 else => |e| return e,
181 } else if (emit.bin_file.cast(.macho)) |macho_file|
182 @enumFromInt(try macho_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, null))163 @enumFromInt(try macho_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, null))
183 else if (emit.bin_file.cast(.coff2)) |coff| @enumFromInt(@intFromEnum(try coff.globalSymbol(164 else if (emit.bin_file.cast(.coff2)) |coff| @enumFromInt(@intFromEnum(try coff.globalSymbol(
184 extern_func.toSlice(&emit.lower.mir).?,165 extern_func.toSlice(&emit.lower.mir).?,
...@@ -313,14 +294,11 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -313,14 +294,11 @@ pub fn emitMir(emit: *Emit) Error!void {
313 .symbol = if (emit.bin_file.cast(.elf)) |elf_file| @enumFromInt(try elf_file.getGlobalSymbol(294 .symbol = if (emit.bin_file.cast(.elf)) |elf_file| @enumFromInt(try elf_file.getGlobalSymbol(
314 "__tls_get_addr",295 "__tls_get_addr",
315 if (comp.config.link_libc) "c" else null,296 if (comp.config.link_libc) "c" else null,
316 )) else if (emit.bin_file.cast(.elf2)) |elf| elf.externSymbol(.{297 )) else if (emit.bin_file.cast(.elf2)) |elf| try elf.externSymbol(.{
317 .name = "__tls_get_addr",298 .name = "__tls_get_addr",
318 .lib_name = if (comp.config.link_libc) "c" else null,299 .lib_name = if (comp.config.link_libc) "c" else null,
319 .type = .FUNC,300 .type = .FUNC,
320 }) catch |err| switch (err) {301 }) else unreachable,
321 error.LinkOnceUnsupported => unreachable,
322 else => |e| return e,
323 } else unreachable,
324 .is_extern = true,302 .is_extern = true,
325 } },303 } },
326 }});304 }});
...@@ -584,37 +562,16 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -584,37 +562,16 @@ pub fn emitMir(emit: *Emit) Error!void {
584 .none => .{ .constu = 0 },562 .none => .{ .constu = 0 },
585 .reg => |reg| .{ .breg = reg.dwarfNum() },563 .reg => |reg| .{ .breg = reg.dwarfNum() },
586 .frame, .table, .rip_inst => unreachable,564 .frame, .table, .rip_inst => unreachable,
587 .nav => |nav| .{ .addr_reloc = switch (codegen.genNavRef(565 .nav => |nav| .{ .addr_reloc = try codegen.genNavRef(
588 emit.bin_file,566 emit.bin_file,
589 emit.pt,567 emit.pt,
590 emit.lower.src_loc,
591 nav,568 nav,
592 emit.lower.target,569 ) },
593 ) catch |err| switch (err) {570 .uav => |uav| .{ .addr_reloc = try emit.bin_file.lowerUav(
594 error.CodegenFail,
595 => return emit.fail("unable to codegen: {s}", .{@errorName(err)}),
596 else => |e| return e,
597 }) {
598 .sym_index => |sym_index| sym_index,
599 .fail => |em| {
600 assert(emit.lower.err_msg == null);
601 emit.lower.err_msg = em;
602 return error.EmitFail;
603 },
604 } },
605 .uav => |uav| .{ .addr_reloc = switch (try emit.bin_file.lowerUav(
606 emit.pt,571 emit.pt,
607 uav.val,572 uav.val,
608 Type.fromInterned(uav.orig_ty).ptrAlignment(emit.pt.zcu),573 Type.fromInterned(uav.orig_ty).ptrAlignment(emit.pt.zcu),
609 emit.lower.src_loc,574 ) },
610 )) {
611 .sym_index => |sym_index| sym_index,
612 .fail => |em| {
613 assert(emit.lower.err_msg == null);
614 emit.lower.err_msg = em;
615 return error.EmitFail;
616 },
617 } },
618 .lazy_sym, .extern_func => unreachable,575 .lazy_sym, .extern_func => unreachable,
619 };576 };
620 break :base &loc_buf[0];577 break :base &loc_buf[0];
...@@ -666,7 +623,6 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -666,7 +623,6 @@ pub fn emitMir(emit: *Emit) Error!void {
666 const local = &emit.lower.mir.locals[local_index];623 const local = &emit.lower.mir.locals[local_index];
667 local_index += 1;624 local_index += 1;
668 try dwarf.genLocalConstDebugInfo(625 try dwarf.genLocalConstDebugInfo(
669 emit.lower.src_loc,
670 switch (mir_inst.ops) {626 switch (mir_inst.ops) {
671 else => unreachable,627 else => unreachable,
672 .pseudo_dbg_arg_val => .comptime_arg,628 .pseudo_dbg_arg_val => .comptime_arg,
src/codegen/x86_64/Lower.zig+2-2
...@@ -49,8 +49,8 @@ pub const Error = error{...@@ -49,8 +49,8 @@ pub const Error = error{
49 LowerFail,49 LowerFail,
50 InvalidInstruction,50 InvalidInstruction,
51 CannotEncode,51 CannotEncode,
52 CodegenFail,52 AlreadyReported,
53} || codegen.GenerateSymbolError;53} || link.Error;
5454
55pub const Reloc = struct {55pub const Reloc = struct {
56 lowered_inst_index: ResultInstIndex,56 lowered_inst_index: ResultInstIndex,
src/codegen/x86_64/Mir.zig+4-6
...@@ -1974,12 +1974,11 @@ pub fn emit(...@@ -1974,12 +1974,11 @@ pub fn emit(
1974 mir: Mir,1974 mir: Mir,
1975 lf: *link.File,1975 lf: *link.File,
1976 pt: Zcu.PerThread,1976 pt: Zcu.PerThread,
1977 src_loc: Zcu.LazySrcLoc,
1978 func_index: InternPool.Index,1977 func_index: InternPool.Index,
1979 atom_id: link.File.AtomId,1978 atom_id: link.File.AtomId,
1980 w: *std.Io.Writer,1979 w: *std.Io.Writer,
1981 debug_output: link.File.DebugInfoOutput,1980 debug_output: link.File.DebugInfoOutput,
1982) codegen.CodeGenError!void {1981) codegen.Error!void {
1983 const zcu = pt.zcu;1982 const zcu = pt.zcu;
1984 const comp = zcu.comp;1983 const comp = zcu.comp;
1985 const gpa = comp.gpa;1984 const gpa = comp.gpa;
...@@ -1993,7 +1992,7 @@ pub fn emit(...@@ -1993,7 +1992,7 @@ pub fn emit(
1993 .allocator = gpa,1992 .allocator = gpa,
1994 .mir = mir,1993 .mir = mir,
1995 .cc = fn_info.cc,1994 .cc = fn_info.cc,
1996 .src_loc = src_loc,1995 .src_loc = zcu.navSrcLoc(nav),
1997 },1996 },
1998 .bin_file = lf,1997 .bin_file = lf,
1999 .pt = pt,1998 .pt = pt,
...@@ -2028,12 +2027,11 @@ pub fn emitLazy(...@@ -2028,12 +2027,11 @@ pub fn emitLazy(
2028 mir: Mir,2027 mir: Mir,
2029 lf: *link.File,2028 lf: *link.File,
2030 pt: Zcu.PerThread,2029 pt: Zcu.PerThread,
2031 src_loc: Zcu.LazySrcLoc,
2032 lazy_sym: link.File.LazySymbol,2030 lazy_sym: link.File.LazySymbol,
2033 atom_id: link.File.AtomId,2031 atom_id: link.File.AtomId,
2034 w: *std.Io.Writer,2032 w: *std.Io.Writer,
2035 debug_output: link.File.DebugInfoOutput,2033 debug_output: link.File.DebugInfoOutput,
2036) codegen.CodeGenError!void {2034) codegen.Error!void {
2037 const zcu = pt.zcu;2035 const zcu = pt.zcu;
2038 const comp = zcu.comp;2036 const comp = zcu.comp;
2039 const gpa = comp.gpa;2037 const gpa = comp.gpa;
...@@ -2044,7 +2042,7 @@ pub fn emitLazy(...@@ -2044,7 +2042,7 @@ pub fn emitLazy(
2044 .allocator = gpa,2042 .allocator = gpa,
2045 .mir = mir,2043 .mir = mir,
2046 .cc = .auto,2044 .cc = .auto,
2047 .src_loc = src_loc,2045 .src_loc = Zcu.Type.fromInterned(lazy_sym.ty).srcLocOrNull(zcu) orelse .unneeded,
2048 },2046 },
2049 .bin_file = lf,2047 .bin_file = lf,
2050 .pt = pt,2048 .pt = pt,
src/link.zig+57-90
...@@ -31,6 +31,12 @@ pub const LdScript = @import("link/LdScript.zig");...@@ -31,6 +31,12 @@ pub const LdScript = @import("link/LdScript.zig");
31pub const Queue = @import("link/Queue.zig");31pub const Queue = @import("link/Queue.zig");
32pub const ConstPool = @import("link/ConstPool.zig");32pub const ConstPool = @import("link/ConstPool.zig");
3333
34pub const Error = Allocator.Error || Io.Cancelable || error{
35 /// An error message has already been stored in persistent state on `Compilation` or `Zcu`, for
36 /// instance in `Compilation.link_diags`.
37 AlreadyReported,
38};
39
34pub const Diags = struct {40pub const Diags = struct {
35 /// Stored here so that function definitions can distinguish between41 /// Stored here so that function definitions can distinguish between
36 /// needing an allocator for things besides error reporting.42 /// needing an allocator for things besides error reporting.
...@@ -112,7 +118,7 @@ pub const Diags = struct {...@@ -112,7 +118,7 @@ pub const Diags = struct {
112 err: ErrorWithNotes,118 err: ErrorWithNotes,
113 comptime format: []const u8,119 comptime format: []const u8,
114 args: anytype,120 args: anytype,
115 ) error{OutOfMemory}!void {121 ) Allocator.Error!void {
116 const gpa = err.diags.gpa;122 const gpa = err.diags.gpa;
117 const err_msg = &err.diags.msgs.items[err.index];123 const err_msg = &err.diags.msgs.items[err.index];
118 err_msg.msg = try std.fmt.allocPrint(gpa, format, args);124 err_msg.msg = try std.fmt.allocPrint(gpa, format, args);
...@@ -212,16 +218,16 @@ pub const Diags = struct {...@@ -212,16 +218,16 @@ pub const Diags = struct {
212 }218 }
213 }219 }
214220
215 pub fn fail(diags: *Diags, comptime format: []const u8, args: anytype) error{LinkFailure} {221 pub fn fail(diags: *Diags, comptime format: []const u8, args: anytype) error{AlreadyReported} {
216 @branchHint(.cold);222 @branchHint(.cold);
217 addError(diags, format, args);223 addError(diags, format, args);
218 return error.LinkFailure;224 return error.AlreadyReported;
219 }225 }
220226
221 pub fn failSourceLocation(diags: *Diags, sl: SourceLocation, comptime format: []const u8, args: anytype) error{LinkFailure} {227 pub fn failSourceLocation(diags: *Diags, sl: SourceLocation, comptime format: []const u8, args: anytype) error{AlreadyReported} {
222 @branchHint(.cold);228 @branchHint(.cold);
223 addErrorSourceLocation(diags, sl, format, args);229 addErrorSourceLocation(diags, sl, format, args);
224 return error.LinkFailure;230 return error.AlreadyReported;
225 }231 }
226232
227 pub fn addError(diags: *Diags, comptime format: []const u8, args: anytype) void {233 pub fn addError(diags: *Diags, comptime format: []const u8, args: anytype) void {
...@@ -251,7 +257,7 @@ pub const Diags = struct {...@@ -251,7 +257,7 @@ pub const Diags = struct {
251 });257 });
252 }258 }
253259
254 pub fn addErrorWithNotes(diags: *Diags, note_count: usize) error{OutOfMemory}!ErrorWithNotes {260 pub fn addErrorWithNotes(diags: *Diags, note_count: usize) Allocator.Error!ErrorWithNotes {
255 @branchHint(.cold);261 @branchHint(.cold);
256 const gpa = diags.gpa;262 const gpa = diags.gpa;
257 const io = diags.io;263 const io = diags.io;
...@@ -261,7 +267,7 @@ pub const Diags = struct {...@@ -261,7 +267,7 @@ pub const Diags = struct {
261 return addErrorWithNotesAssumeCapacity(diags, note_count);267 return addErrorWithNotesAssumeCapacity(diags, note_count);
262 }268 }
263269
264 pub fn addErrorWithNotesAssumeCapacity(diags: *Diags, note_count: usize) error{OutOfMemory}!ErrorWithNotes {270 pub fn addErrorWithNotesAssumeCapacity(diags: *Diags, note_count: usize) Allocator.Error!ErrorWithNotes {
265 @branchHint(.cold);271 @branchHint(.cold);
266 const gpa = diags.gpa;272 const gpa = diags.gpa;
267 const index = diags.msgs.items.len;273 const index = diags.msgs.items.len;
...@@ -351,10 +357,10 @@ pub const Diags = struct {...@@ -351,10 +357,10 @@ pub const Diags = struct {
351 path: Path,357 path: Path,
352 comptime format: []const u8,358 comptime format: []const u8,
353 args: anytype,359 args: anytype,
354 ) error{LinkFailure} {360 ) error{AlreadyReported} {
355 @branchHint(.cold);361 @branchHint(.cold);
356 addParseError(diags, path, format, args);362 addParseError(diags, path, format, args);
357 return error.LinkFailure;363 return error.AlreadyReported;
358 }364 }
359365
360 pub fn setAllocFailure(diags: *Diags) void {366 pub fn setAllocFailure(diags: *Diags) void {
...@@ -752,11 +758,6 @@ pub const File = struct {...@@ -752,11 +758,6 @@ pub const File = struct {
752 none,758 none,
753 };759 };
754 pub const UpdateDebugInfoError = Dwarf.UpdateError;760 pub const UpdateDebugInfoError = Dwarf.UpdateError;
755 pub const FlushDebugInfoError = Dwarf.FlushError;
756
757 /// Note that `LinkFailure` is not a member of this error set because the error message
758 /// must be attached to `Zcu.failed_codegen` rather than `Compilation.link_diags`.
759 pub const UpdateNavError = codegen.CodeGenError;
760761
761 /// Opaque identifier for a function currently being emitted.762 /// Opaque identifier for a function currently being emitted.
762 ///763 ///
...@@ -775,7 +776,7 @@ pub const File = struct {...@@ -775,7 +776,7 @@ pub const File = struct {
775 /// be created. This symbol may get resolved once all relocatables are (re-)linked.776 /// be created. This symbol may get resolved once all relocatables are (re-)linked.
776 /// Optionally, it is possible to specify where to expect the symbol defined if it777 /// Optionally, it is possible to specify where to expect the symbol defined if it
777 /// is an import.778 /// is an import.
778 pub fn getGlobalSymbol(base: *File, name: []const u8, lib_name: ?[]const u8) UpdateNavError!SymbolId {779 pub fn getGlobalSymbol(base: *File, name: []const u8, lib_name: ?[]const u8) Error!SymbolId {
779 log.debug("getGlobalSymbol '{s}' (expected in '{?s}')", .{ name, lib_name });780 log.debug("getGlobalSymbol '{s}' (expected in '{?s}')", .{ name, lib_name });
780 switch (base.tag) {781 switch (base.tag) {
781 .lld => unreachable,782 .lld => unreachable,
...@@ -790,7 +791,7 @@ pub const File = struct {...@@ -790,7 +791,7 @@ pub const File = struct {
790791
791 /// May be called before or after updateExports for any given Nav.792 /// May be called before or after updateExports for any given Nav.
792 /// Asserts that the ZCU is not using the LLVM backend.793 /// Asserts that the ZCU is not using the LLVM backend.
793 fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) UpdateNavError!void {794 fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) Error!void {
794 assert(base.comp.zcu.?.llvm_object == null);795 assert(base.comp.zcu.?.llvm_object == null);
795 const nav = pt.zcu.intern_pool.getNav(nav_index);796 const nav = pt.zcu.intern_pool.getNav(nav_index);
796 assert(nav.resolved.?.value != .none);797 assert(nav.resolved.?.value != .none);
...@@ -804,14 +805,8 @@ pub const File = struct {...@@ -804,14 +805,8 @@ pub const File = struct {
804 }805 }
805 }806 }
806807
807 pub const UpdateContainerTypeError = error{
808 OutOfMemory,
809 /// `Zcu.failed_types` is already populated with the error message.
810 TypeFailureReported,
811 };
812
813 /// Never called when LLVM is codegenning the ZCU.808 /// Never called when LLVM is codegenning the ZCU.
814 fn updateContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) UpdateContainerTypeError!void {809 fn updateContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) Error!void {
815 assert(base.comp.zcu.?.llvm_object == null);810 assert(base.comp.zcu.?.llvm_object == null);
816 switch (base.tag) {811 switch (base.tag) {
817 .lld => unreachable,812 .lld => unreachable,
...@@ -824,7 +819,7 @@ pub const File = struct {...@@ -824,7 +819,7 @@ pub const File = struct {
824 }819 }
825820
826 /// Never called when LLVM is codegenning the ZCU.821 /// Never called when LLVM is codegenning the ZCU.
827 fn clearContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index) UpdateContainerTypeError!void {822 fn clearContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index) Error!void {
828 assert(base.comp.zcu.?.llvm_object == null);823 assert(base.comp.zcu.?.llvm_object == null);
829 switch (base.tag) {824 switch (base.tag) {
830 .lld => unreachable,825 .lld => unreachable,
...@@ -847,7 +842,7 @@ pub const File = struct {...@@ -847,7 +842,7 @@ pub const File = struct {
847 /// that `mir.deinit` remains legal for the caller. For instance, the callee can842 /// that `mir.deinit` remains legal for the caller. For instance, the callee can
848 /// take ownership of an embedded slice and replace it with `&.{}` in `mir`.843 /// take ownership of an embedded slice and replace it with `&.{}` in `mir`.
849 mir: *codegen.AnyMir,844 mir: *codegen.AnyMir,
850 ) UpdateNavError!void {845 ) Error!void {
851 assert(base.comp.zcu.?.llvm_object == null);846 assert(base.comp.zcu.?.llvm_object == null);
852 switch (base.tag) {847 switch (base.tag) {
853 .lld => unreachable,848 .lld => unreachable,
...@@ -860,16 +855,10 @@ pub const File = struct {...@@ -860,16 +855,10 @@ pub const File = struct {
860 }855 }
861 }856 }
862857
863 pub const UpdateLineNumberError = error{
864 OutOfMemory,
865 Overflow,
866 LinkFailure,
867 };
868
869 /// On an incremental update, fixup the line number of all `Nav`s at the given `TrackedInst`, because858 /// On an incremental update, fixup the line number of all `Nav`s at the given `TrackedInst`, because
870 /// its line number has changed. The ZIR instruction `ti_id` has tag `.declaration`.859 /// its line number has changed. The ZIR instruction `ti_id` has tag `.declaration`.
871 /// Never called when LLVM is codegenning the ZCU.860 /// Never called when LLVM is codegenning the ZCU.
872 fn updateLineNumber(base: *File, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) UpdateLineNumberError!void {861 fn updateLineNumber(base: *File, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) Error!void {
873 assert(base.comp.zcu.?.llvm_object == null);862 assert(base.comp.zcu.?.llvm_object == null);
874 {863 {
875 const ti = ti_id.resolveFull(&pt.zcu.intern_pool).?;864 const ti = ti_id.resolveFull(&pt.zcu.intern_pool).?;
...@@ -918,7 +907,7 @@ pub const File = struct {...@@ -918,7 +907,7 @@ pub const File = struct {
918 }907 }
919 }908 }
920909
921 pub fn idle(base: *File, tid: Zcu.PerThread.Id) !bool {910 pub fn idle(base: *File, tid: Zcu.PerThread.Id) Error!bool {
922 switch (base.tag) {911 switch (base.tag) {
923 else => return false,912 else => return false,
924 inline .elf2, .coff2 => |tag| {913 inline .elf2, .coff2 => |tag| {
...@@ -928,7 +917,7 @@ pub const File = struct {...@@ -928,7 +917,7 @@ pub const File = struct {
928 }917 }
929 }918 }
930919
931 pub fn updateErrorData(base: *File, pt: Zcu.PerThread) !void {920 pub fn updateErrorData(base: *File, pt: Zcu.PerThread) Error!void {
932 switch (base.tag) {921 switch (base.tag) {
933 else => {},922 else => {},
934 inline .elf2, .coff2 => |tag| {923 inline .elf2, .coff2 => |tag| {
...@@ -938,14 +927,9 @@ pub const File = struct {...@@ -938,14 +927,9 @@ pub const File = struct {
938 }927 }
939 }928 }
940929
941 pub const FlushError = Io.Cancelable || Allocator.Error || error{
942 /// Indicates an error will be present in `Compilation.link_diags`.
943 LinkFailure,
944 };
945
946 /// Commit pending changes and write headers. Takes into account final output mode.930 /// Commit pending changes and write headers. Takes into account final output mode.
947 /// `arena` has the lifetime of the call to `Compilation.update`.931 /// `arena` has the lifetime of the call to `Compilation.update`.
948 pub fn flush(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void {932 pub fn flush(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) Error!void {
949 const comp = base.comp;933 const comp = base.comp;
950 const io = comp.io;934 const io = comp.io;
951 if (comp.clang_preprocessor_mode == .yes or comp.clang_preprocessor_mode == .pch) {935 if (comp.clang_preprocessor_mode == .yes or comp.clang_preprocessor_mode == .pch) {
...@@ -985,11 +969,6 @@ pub const File = struct {...@@ -985,11 +969,6 @@ pub const File = struct {
985 }969 }
986 }970 }
987971
988 pub const UpdateExportsError = error{
989 OutOfMemory,
990 AnalysisFail,
991 };
992
993 /// This is called for every exported thing. `exports` is almost always972 /// This is called for every exported thing. `exports` is almost always
994 /// a list of size 1, meaning that `exported` is exported once. However, it is possible973 /// a list of size 1, meaning that `exported` is exported once. However, it is possible
995 /// to export the same thing with multiple different symbol names (aliases).974 /// to export the same thing with multiple different symbol names (aliases).
...@@ -1000,7 +979,7 @@ pub const File = struct {...@@ -1000,7 +979,7 @@ pub const File = struct {
1000 pt: Zcu.PerThread,979 pt: Zcu.PerThread,
1001 exported: Zcu.Exported,980 exported: Zcu.Exported,
1002 export_indices: []const Zcu.Export.Index,981 export_indices: []const Zcu.Export.Index,
1003 ) UpdateExportsError!void {982 ) Error!void {
1004 assert(base.comp.zcu.?.llvm_object == null);983 assert(base.comp.zcu.?.llvm_object == null);
1005 switch (base.tag) {984 switch (base.tag) {
1006 .lld => unreachable,985 .lld => unreachable,
...@@ -1031,7 +1010,7 @@ pub const File = struct {...@@ -1031,7 +1010,7 @@ pub const File = struct {
1031 /// May be called before or after updateFunc/updateNav therefore it is up to the linker to allocate1010 /// May be called before or after updateFunc/updateNav therefore it is up to the linker to allocate
1032 /// the block/atom.1011 /// the block/atom.
1033 /// Never called when LLVM is codegenning the ZCU.1012 /// Never called when LLVM is codegenning the ZCU.
1034 pub fn getNavVAddr(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: RelocInfo) !u64 {1013 pub fn getNavVAddr(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: RelocInfo) Error!u64 {
1035 assert(base.comp.zcu.?.llvm_object == null);1014 assert(base.comp.zcu.?.llvm_object == null);
1036 switch (base.tag) {1015 switch (base.tag) {
1037 .lld => unreachable,1016 .lld => unreachable,
...@@ -1052,8 +1031,7 @@ pub const File = struct {...@@ -1052,8 +1031,7 @@ pub const File = struct {
1052 pt: Zcu.PerThread,1031 pt: Zcu.PerThread,
1053 decl_val: InternPool.Index,1032 decl_val: InternPool.Index,
1054 decl_align: InternPool.Alignment,1033 decl_align: InternPool.Alignment,
1055 src_loc: Zcu.LazySrcLoc,1034 ) Error!SymbolId {
1056 ) !codegen.SymbolResult {
1057 assert(base.comp.zcu.?.llvm_object == null);1035 assert(base.comp.zcu.?.llvm_object == null);
1058 switch (base.tag) {1036 switch (base.tag) {
1059 .lld => unreachable,1037 .lld => unreachable,
...@@ -1063,13 +1041,13 @@ pub const File = struct {...@@ -1063,13 +1041,13 @@ pub const File = struct {
1063 .plan9 => unreachable,1041 .plan9 => unreachable,
1064 inline else => |tag| {1042 inline else => |tag| {
1065 dev.check(tag.devFeature());1043 dev.check(tag.devFeature());
1066 return @as(*tag.Type(), @fieldParentPtr("base", base)).lowerUav(pt, decl_val, decl_align, src_loc);1044 return @as(*tag.Type(), @fieldParentPtr("base", base)).lowerUav(pt, decl_val, decl_align);
1067 },1045 },
1068 }1046 }
1069 }1047 }
10701048
1071 /// Never called when LLVM is codegenning the ZCU.1049 /// Never called when LLVM is codegenning the ZCU.
1072 pub fn getUavVAddr(base: *File, decl_val: InternPool.Index, reloc_info: RelocInfo) !u64 {1050 pub fn getUavVAddr(base: *File, decl_val: InternPool.Index, reloc_info: RelocInfo) Error!u64 {
1073 assert(base.comp.zcu.?.llvm_object == null);1051 assert(base.comp.zcu.?.llvm_object == null);
1074 switch (base.tag) {1052 switch (base.tag) {
1075 .lld => unreachable,1053 .lld => unreachable,
...@@ -1217,7 +1195,7 @@ pub const File = struct {...@@ -1217,7 +1195,7 @@ pub const File = struct {
12171195
1218 /// Called when all linker inputs have been sent via `loadInput`. After1196 /// Called when all linker inputs have been sent via `loadInput`. After
1219 /// this, `loadInput` will not be called anymore.1197 /// this, `loadInput` will not be called anymore.
1220 pub fn prelink(base: *File) FlushError!void {1198 pub fn prelink(base: *File) Error!void {
1221 assert(!base.post_prelink);1199 assert(!base.post_prelink);
12221200
1223 // In this case, an object file is created by the LLVM backend, so1201 // In this case, an object file is created by the LLVM backend, so
...@@ -1251,7 +1229,11 @@ pub const File = struct {...@@ -1251,7 +1229,11 @@ pub const File = struct {
1251 file_writer.pos = new_offset;1229 file_writer.pos = new_offset;
1252 const size_u = std.math.cast(usize, size) orelse return error.Overflow;1230 const size_u = std.math.cast(usize, size) orelse return error.Overflow;
1253 const n = file_writer.interface.sendFileAll(&file_reader, .limited(size_u)) catch |err| switch (err) {1231 const n = file_writer.interface.sendFileAll(&file_reader, .limited(size_u)) catch |err| switch (err) {
1254 error.ReadFailed => return file_reader.err.?,1232 error.ReadFailed => switch (file_reader.err.?) {
1233 error.ConnectionResetByPeer => return error.Unexpected, // not a socket
1234 error.SocketUnconnected => return error.Unexpected, // not a socket
1235 else => |e| return e,
1236 },
1255 error.WriteFailed => return file_writer.err.?,1237 error.WriteFailed => return file_writer.err.?,
1256 };1238 };
1257 assert(n == size_u);1239 assert(n == size_u);
...@@ -1367,7 +1349,7 @@ pub const File = struct {...@@ -1367,7 +1349,7 @@ pub const File = struct {
1367 nav_index: InternPool.Nav.Index,1349 nav_index: InternPool.Nav.Index,
1368 comptime format: []const u8,1350 comptime format: []const u8,
1369 args: anytype,1351 args: anytype,
1370 ) error{ CodegenFail, OutOfMemory } {1352 ) Zcu.CodegenFailError {
1371 @branchHint(.cold);1353 @branchHint(.cold);
1372 return base.comp.zcu.?.codegenFail(nav_index, format, args);1354 return base.comp.zcu.?.codegenFail(nav_index, format, args);
1373 }1355 }
...@@ -1440,7 +1422,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {...@@ -1440,7 +1422,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
1440 defer prog_node.end();1422 defer prog_node.end();
1441 for (comp.link_inputs) |input| {1423 for (comp.link_inputs) |input| {
1442 base.loadInput(input) catch |err| switch (err) {1424 base.loadInput(input) catch |err| switch (err) {
1443 error.LinkFailure => return, // error reported via diags1425 error.AlreadyReported => return, // error reported via diags
1444 else => |e| switch (input) {1426 else => |e| switch (input) {
1445 .dso => |dso| diags.addParseError(dso.path, "failed to parse shared library: {s}", .{@errorName(e)}),1427 .dso => |dso| diags.addParseError(dso.path, "failed to parse shared library: {s}", .{@errorName(e)}),
1446 .object => |obj| diags.addParseError(obj.path, "failed to parse object: {s}", .{@errorName(e)}),1428 .object => |obj| diags.addParseError(obj.path, "failed to parse object: {s}", .{@errorName(e)}),
...@@ -1485,11 +1467,11 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {...@@ -1485,11 +1467,11 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
1485 .preferred_mode = .dynamic,1467 .preferred_mode = .dynamic,
1486 .search_strategy = .paths_first,1468 .search_strategy = .paths_first,
1487 }) catch |archive_err| switch (archive_err) {1469 }) catch |archive_err| switch (archive_err) {
1488 error.LinkFailure => return, // error reported via diags1470 error.AlreadyReported => return, // error reported via diags
1489 else => |e| diags.addParseError(dso_path, "failed to parse archive {f}: {s}", .{ archive_path, @errorName(e) }),1471 else => |e| diags.addParseError(dso_path, "failed to parse archive {f}: {s}", .{ archive_path, @errorName(e) }),
1490 };1472 };
1491 },1473 },
1492 error.LinkFailure => return, // error reported via diags1474 error.AlreadyReported => return, // error reported via diags
1493 else => |e| diags.addParseError(dso_path, "failed to parse shared library: {s}", .{@errorName(e)}),1475 else => |e| diags.addParseError(dso_path, "failed to parse shared library: {s}", .{@errorName(e)}),
1494 };1476 };
1495 },1477 },
...@@ -1504,7 +1486,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {...@@ -1504,7 +1486,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
1504 .preferred_mode = .static,1486 .preferred_mode = .static,
1505 .search_strategy = .no_fallback,1487 .search_strategy = .no_fallback,
1506 }) catch |err| switch (err) {1488 }) catch |err| switch (err) {
1507 error.LinkFailure => return, // error reported via diags1489 error.AlreadyReported => return, // error reported via diags
1508 else => |e| diags.addParseError(path, "failed to parse archive: {s}", .{@errorName(e)}),1490 else => |e| diags.addParseError(path, "failed to parse archive: {s}", .{@errorName(e)}),
1509 };1491 };
1510 },1492 },
...@@ -1515,7 +1497,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {...@@ -1515,7 +1497,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
1515 const prog_node = comp.link_prog_node.start("Parse Object", 0);1497 const prog_node = comp.link_prog_node.start("Parse Object", 0);
1516 defer prog_node.end();1498 defer prog_node.end();
1517 base.openLoadObject(path) catch |err| switch (err) {1499 base.openLoadObject(path) catch |err| switch (err) {
1518 error.LinkFailure => return, // error reported via diags1500 error.AlreadyReported => return, // error reported via diags
1519 else => |e| diags.addParseError(path, "failed to parse object: {s}", .{@errorName(e)}),1501 else => |e| diags.addParseError(path, "failed to parse object: {s}", .{@errorName(e)}),
1520 };1502 };
1521 },1503 },
...@@ -1523,7 +1505,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {...@@ -1523,7 +1505,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
1523 const prog_node = comp.link_prog_node.start("Parse Archive", 0);1505 const prog_node = comp.link_prog_node.start("Parse Archive", 0);
1524 defer prog_node.end();1506 defer prog_node.end();
1525 base.openLoadArchive(load_archive.path, load_archive.must_link) catch |err| switch (err) {1507 base.openLoadArchive(load_archive.path, load_archive.must_link) catch |err| switch (err) {
1526 error.LinkFailure => return, // error reported via link_diags1508 error.AlreadyReported => return, // error reported via link_diags
1527 else => |e| diags.addParseError(load_archive.path, "failed to parse archive: {s}", .{@errorName(e)}),1509 else => |e| diags.addParseError(load_archive.path, "failed to parse archive: {s}", .{@errorName(e)}),
1528 };1510 };
1529 },1511 },
...@@ -1534,7 +1516,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {...@@ -1534,7 +1516,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
1534 .preferred_mode = .dynamic,1516 .preferred_mode = .dynamic,
1535 .search_strategy = .paths_first,1517 .search_strategy = .paths_first,
1536 }) catch |err| switch (err) {1518 }) catch |err| switch (err) {
1537 error.LinkFailure => return, // error reported via link_diags1519 error.AlreadyReported => return, // error reported via link_diags
1538 else => |e| diags.addParseError(path, "failed to parse shared library: {s}", .{@errorName(e)}),1520 else => |e| diags.addParseError(path, "failed to parse shared library: {s}", .{@errorName(e)}),
1539 };1521 };
1540 },1522 },
...@@ -1561,15 +1543,9 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void...@@ -1561,15 +1543,9 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void
1561 };1543 };
1562 } else if (comp.bin_file) |lf| {1544 } else if (comp.bin_file) |lf| {
1563 lf.updateNav(pt, nav_index) catch |err| switch (err) {1545 lf.updateNav(pt, nav_index) catch |err| switch (err) {
1546 error.Canceled => io.recancel(),
1547 error.AlreadyReported => return,
1564 error.OutOfMemory => diags.setAllocFailure(),1548 error.OutOfMemory => diags.setAllocFailure(),
1565 error.CodegenFail => zcu.assertCodegenFailed(nav_index),
1566 error.Overflow, error.RelocationNotByteAligned => {
1567 switch (zcu.codegenFail(nav_index, "unable to codegen: {s}", .{@errorName(err)})) {
1568 error.CodegenFail => return,
1569 error.OutOfMemory => return diags.setAllocFailure(),
1570 }
1571 // Not a retryable failure.
1572 },
1573 };1549 };
1574 }1550 }
1575 break :nav nav_index;1551 break :nav nav_index;
...@@ -1594,14 +1570,9 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void...@@ -1594,14 +1570,9 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void
1594 assert(zcu.llvm_object == null); // LLVM codegen doesn't produce MIR1570 assert(zcu.llvm_object == null); // LLVM codegen doesn't produce MIR
1595 if (comp.bin_file) |lf| {1571 if (comp.bin_file) |lf| {
1596 lf.updateFunc(pt, func, &mir) catch |err| switch (err) {1572 lf.updateFunc(pt, func, &mir) catch |err| switch (err) {
1573 error.Canceled => io.recancel(),
1574 error.AlreadyReported => return,
1597 error.OutOfMemory => return diags.setAllocFailure(),1575 error.OutOfMemory => return diags.setAllocFailure(),
1598 error.CodegenFail => return zcu.assertCodegenFailed(nav),
1599 error.Overflow, error.RelocationNotByteAligned => {
1600 switch (zcu.codegenFail(nav, "unable to codegen: {s}", .{@errorName(err)})) {
1601 error.OutOfMemory => return diags.setAllocFailure(),
1602 error.CodegenFail => return,
1603 }
1604 },
1605 };1576 };
1606 }1577 }
1607 break :nav ip.indexToKey(func).func.owner_nav;1578 break :nav ip.indexToKey(func).func.owner_nav;
...@@ -1618,7 +1589,8 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void...@@ -1618,7 +1589,8 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void
1618 if (comp.bin_file) |lf| {1589 if (comp.bin_file) |lf| {
1619 lf.updateContainerType(pt, container_update.ty, container_update.success) catch |err| switch (err) {1590 lf.updateContainerType(pt, container_update.ty, container_update.success) catch |err| switch (err) {
1620 error.OutOfMemory => diags.setAllocFailure(),1591 error.OutOfMemory => diags.setAllocFailure(),
1621 error.TypeFailureReported => assert(zcu.failed_types.contains(container_update.ty)),1592 error.Canceled => io.recancel(),
1593 error.AlreadyReported => {},
1622 };1594 };
1623 }1595 }
1624 }1596 }
...@@ -1657,7 +1629,7 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void...@@ -1657,7 +1629,7 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void
1657 }1629 }
1658 }1630 }
1659}1631}
1660pub fn doIdleTask(comp: *Compilation, tid: Zcu.PerThread.Id) error{ OutOfMemory, LinkFailure }!bool {1632pub fn doIdleTask(comp: *Compilation, tid: Zcu.PerThread.Id) Error!bool {
1661 return if (comp.bin_file) |lf| lf.idle(tid) else false;1633 return if (comp.bin_file) |lf| lf.idle(tid) else false;
1662}1634}
1663/// After the main pipeline is done, but before flush, the compilation may need to link one final1635/// After the main pipeline is done, but before flush, the compilation may need to link one final
...@@ -1673,15 +1645,9 @@ pub fn linkTestFunctionsNav(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)...@@ -1673,15 +1645,9 @@ pub fn linkTestFunctionsNav(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)
1673 };1645 };
1674 } else if (comp.bin_file) |lf| {1646 } else if (comp.bin_file) |lf| {
1675 lf.updateNav(pt, nav_index) catch |err| switch (err) {1647 lf.updateNav(pt, nav_index) catch |err| switch (err) {
1648 error.Canceled => comp.io.recancel(),
1649 error.AlreadyReported => return,
1676 error.OutOfMemory => diags.setAllocFailure(),1650 error.OutOfMemory => diags.setAllocFailure(),
1677 error.CodegenFail => zcu.assertCodegenFailed(nav_index),
1678 error.Overflow, error.RelocationNotByteAligned => {
1679 switch (zcu.codegenFail(nav_index, "unable to codegen: {s}", .{@errorName(err)})) {
1680 error.CodegenFail => return,
1681 error.OutOfMemory => return diags.setAllocFailure(),
1682 }
1683 // Not a retryable failure.
1684 },
1685 };1651 };
1686 }1652 }
1687}1653}
...@@ -1689,7 +1655,8 @@ pub fn updateErrorData(pt: Zcu.PerThread) void {...@@ -1689,7 +1655,8 @@ pub fn updateErrorData(pt: Zcu.PerThread) void {
1689 const comp = pt.zcu.comp;1655 const comp = pt.zcu.comp;
1690 if (comp.bin_file) |lf| lf.updateErrorData(pt) catch |err| switch (err) {1656 if (comp.bin_file) |lf| lf.updateErrorData(pt) catch |err| switch (err) {
1691 error.OutOfMemory => comp.link_diags.setAllocFailure(),1657 error.OutOfMemory => comp.link_diags.setAllocFailure(),
1692 error.LinkFailure => {},1658 error.Canceled => comp.io.recancel(),
1659 error.AlreadyReported => {},
1693 };1660 };
1694}1661}
16951662
...@@ -2428,19 +2395,19 @@ pub fn openDso(io: Io, path: Path, needed: bool, weak: bool, reexport: bool) !In...@@ -2428,19 +2395,19 @@ pub fn openDso(io: Io, path: Path, needed: bool, weak: bool, reexport: bool) !In
2428 };2395 };
2429}2396}
24302397
2431pub fn openObjectInput(io: Io, diags: *Diags, path: Path) error{LinkFailure}!Input {2398pub fn openObjectInput(io: Io, diags: *Diags, path: Path) error{AlreadyReported}!Input {
2432 return .{ .object = openObject(io, path, false, false) catch |err| {2399 return .{ .object = openObject(io, path, false, false) catch |err| {
2433 return diags.failParse(path, "failed to open {f}: {s}", .{ path, @errorName(err) });2400 return diags.failParse(path, "failed to open {f}: {s}", .{ path, @errorName(err) });
2434 } };2401 } };
2435}2402}
24362403
2437pub fn openArchiveInput(io: Io, diags: *Diags, path: Path, must_link: bool, hidden: bool) error{LinkFailure}!Input {2404pub fn openArchiveInput(io: Io, diags: *Diags, path: Path, must_link: bool, hidden: bool) error{AlreadyReported}!Input {
2438 return .{ .archive = openObject(io, path, must_link, hidden) catch |err| {2405 return .{ .archive = openObject(io, path, must_link, hidden) catch |err| {
2439 return diags.failParse(path, "failed to open {f}: {s}", .{ path, @errorName(err) });2406 return diags.failParse(path, "failed to open {f}: {s}", .{ path, @errorName(err) });
2440 } };2407 } };
2441}2408}
24422409
2443pub fn openDsoInput(io: Io, diags: *Diags, path: Path, needed: bool, weak: bool, reexport: bool) error{LinkFailure}!Input {2410pub fn openDsoInput(io: Io, diags: *Diags, path: Path, needed: bool, weak: bool, reexport: bool) error{AlreadyReported}!Input {
2444 return .{ .dso = openDso(io, path, needed, weak, reexport) catch |err| {2411 return .{ .dso = openDso(io, path, needed, weak, reexport) catch |err| {
2445 return diags.failParse(path, "failed to open {f}: {s}", .{ path, @errorName(err) });2412 return diags.failParse(path, "failed to open {f}: {s}", .{ path, @errorName(err) });
2446 } };2413 } };
src/link/C.zig+8-22
...@@ -474,7 +474,7 @@ pub fn updateContainerType(...@@ -474,7 +474,7 @@ pub fn updateContainerType(
474 pt: Zcu.PerThread,474 pt: Zcu.PerThread,
475 ty: InternPool.Index,475 ty: InternPool.Index,
476 success: bool,476 success: bool,
477) link.File.UpdateContainerTypeError!void {477) link.Error!void {
478 try c.type_pool.updateContainerType(pt, .{ .c = c }, ty, success);478 try c.type_pool.updateContainerType(pt, .{ .c = c }, ty, success);
479}479}
480480
...@@ -570,7 +570,6 @@ pub fn updateNav(...@@ -570,7 +570,6 @@ pub fn updateNav(
570 .arena = arena.allocator(),570 .arena = arena.allocator(),
571 .pt = pt,571 .pt = pt,
572 .mod = zcu.navFileScope(nav_index).mod.?,572 .mod = zcu.navFileScope(nav_index).mod.?,
573 .error_msg = null,
574 .owner_nav = nav_index.toOptional(),573 .owner_nav = nav_index.toOptional(),
575 .is_naked_fn = false,574 .is_naked_fn = false,
576 .expected_block = null,575 .expected_block = null,
...@@ -588,10 +587,7 @@ pub fn updateNav(...@@ -588,10 +587,7 @@ pub fn updateNav(
588 defer c.string_bytes = aw.toArrayList();587 defer c.string_bytes = aw.toArrayList();
589 const start = aw.written().len;588 const start = aw.written().len;
590 codegen.genDeclFwd(&dg, &aw.writer) catch |err| switch (err) {589 codegen.genDeclFwd(&dg, &aw.writer) catch |err| switch (err) {
591 error.AnalysisFail => switch (zcu.codegenFailMsg(nav_index, dg.error_msg.?)) {590 error.AlreadyReported => return,
592 error.CodegenFail => return,
593 error.OutOfMemory => |e| return e,
594 },
595 error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,591 error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
596 };592 };
597 break :fwd_decl .{593 break :fwd_decl .{
...@@ -605,10 +601,7 @@ pub fn updateNav(...@@ -605,10 +601,7 @@ pub fn updateNav(
605 defer c.string_bytes = aw.toArrayList();601 defer c.string_bytes = aw.toArrayList();
606 const start = aw.written().len;602 const start = aw.written().len;
607 codegen.genDecl(&dg, &aw.writer) catch |err| switch (err) {603 codegen.genDecl(&dg, &aw.writer) catch |err| switch (err) {
608 error.AnalysisFail => switch (zcu.codegenFailMsg(nav_index, dg.error_msg.?)) {604 error.AlreadyReported => return,
609 error.CodegenFail => return,
610 error.OutOfMemory => |e| return e,
611 },
612 error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,605 error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
613 };606 };
614 break :code .{607 break :code .{
...@@ -661,7 +654,6 @@ fn updateUav(...@@ -661,7 +654,6 @@ fn updateUav(
661 .arena = arena.allocator(),654 .arena = arena.allocator(),
662 .pt = pt,655 .pt = pt,
663 .mod = pt.zcu.root_mod,656 .mod = pt.zcu.root_mod,
664 .error_msg = null,
665 .owner_nav = .none,657 .owner_nav = .none,
666 .is_naked_fn = false,658 .is_naked_fn = false,
667 .expected_block = null,659 .expected_block = null,
...@@ -683,9 +675,7 @@ fn updateUav(...@@ -683,9 +675,7 @@ fn updateUav(
683 .@"threadlocal" = false,675 .@"threadlocal" = false,
684 .init_val = val,676 .init_val = val,
685 }) catch |err| switch (err) {677 }) catch |err| switch (err) {
686 error.AnalysisFail => {678 error.AlreadyReported => return,
687 @panic("TODO: CBE error.AnalysisFail on uav");
688 },
689 error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,679 error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
690 };680 };
691 break :fwd_decl .{681 break :fwd_decl .{
...@@ -704,9 +694,7 @@ fn updateUav(...@@ -704,9 +694,7 @@ fn updateUav(
704 .@"threadlocal" = false,694 .@"threadlocal" = false,
705 .init_val = val,695 .init_val = val,
706 }) catch |err| switch (err) {696 }) catch |err| switch (err) {
707 error.AnalysisFail => {697 error.AlreadyReported => return,
708 @panic("TODO: CBE error.AnalysisFail on uav");
709 },
710 error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,698 error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
711 };699 };
712 break :code .{700 break :code .{
...@@ -726,7 +714,7 @@ pub fn updateLineNumber(c: *C, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst....@@ -726,7 +714,7 @@ pub fn updateLineNumber(c: *C, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.
726 _ = ti_id;714 _ = ti_id;
727}715}
728716
729pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {717pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.Error!void {
730 const tracy = trace(@src());718 const tracy = trace(@src());
731 defer tracy.end();719 defer tracy.end();
732720
...@@ -1112,7 +1100,6 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog...@@ -1112,7 +1100,6 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
1112 .owner_nav = .none,1100 .owner_nav = .none,
1113 .is_naked_fn = false,1101 .is_naked_fn = false,
1114 .expected_block = null,1102 .expected_block = null,
1115 .error_msg = null,
1116 .ctype_deps = .empty,1103 .ctype_deps = .empty,
1117 .uavs = .empty,1104 .uavs = .empty,
1118 };1105 };
...@@ -1156,14 +1143,14 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog...@@ -1156,14 +1143,14 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
1156 codegen.genLazyCallModifierFn(&lazy_dg, fn_nav, .never_tail, &lazy_decls_aw.writer) catch |err| switch (err) {1143 codegen.genLazyCallModifierFn(&lazy_dg, fn_nav, .never_tail, &lazy_decls_aw.writer) catch |err| switch (err) {
1157 error.WriteFailed => return error.OutOfMemory,1144 error.WriteFailed => return error.OutOfMemory,
1158 error.OutOfMemory => |e| return e,1145 error.OutOfMemory => |e| return e,
1159 error.AnalysisFail => unreachable,1146 error.AlreadyReported => unreachable,
1160 };1147 };
1161 }1148 }
1162 for (need_never_inline_funcs.keys()) |fn_nav| {1149 for (need_never_inline_funcs.keys()) |fn_nav| {
1163 codegen.genLazyCallModifierFn(&lazy_dg, fn_nav, .never_inline, &lazy_decls_aw.writer) catch |err| switch (err) {1150 codegen.genLazyCallModifierFn(&lazy_dg, fn_nav, .never_inline, &lazy_decls_aw.writer) catch |err| switch (err) {
1164 error.WriteFailed => return error.OutOfMemory,1151 error.WriteFailed => return error.OutOfMemory,
1165 error.OutOfMemory => |e| return e,1152 error.OutOfMemory => |e| return e,
1166 error.AnalysisFail => unreachable,1153 error.AlreadyReported => unreachable,
1167 };1154 };
1168 }1155 }
1169 }1156 }
...@@ -1256,7 +1243,6 @@ pub fn updateExports(...@@ -1256,7 +1243,6 @@ pub fn updateExports(
1256 .owner_nav = .none,1243 .owner_nav = .none,
1257 .is_naked_fn = false,1244 .is_naked_fn = false,
1258 .expected_block = null,1245 .expected_block = null,
1259 .error_msg = null,
1260 .ctype_deps = .empty,1246 .ctype_deps = .empty,
1261 .uavs = .empty,1247 .uavs = .empty,
1262 };1248 };
src/link/Coff.zig+31-60
...@@ -43,7 +43,6 @@ lazy: std.EnumArray(link.File.LazySymbol.Kind, struct {...@@ -43,7 +43,6 @@ lazy: std.EnumArray(link.File.LazySymbol.Kind, struct {
43}),43}),
44pending_uavs: std.AutoArrayHashMapUnmanaged(Node.UavMapIndex, struct {44pending_uavs: std.AutoArrayHashMapUnmanaged(Node.UavMapIndex, struct {
45 alignment: InternPool.Alignment,45 alignment: InternPool.Alignment,
46 src_loc: Zcu.LazySrcLoc,
47}),46}),
48relocs: std.ArrayList(Reloc),47relocs: std.ArrayList(Reloc),
49const_prog_node: std.Progress.Node,48const_prog_node: std.Progress.Node,
...@@ -1532,11 +1531,8 @@ pub fn prelink(coff: *Coff, prog_node: std.Progress.Node) void {...@@ -1532,11 +1531,8 @@ pub fn prelink(coff: *Coff, prog_node: std.Progress.Node) void {
15321531
1533pub fn updateNav(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {1532pub fn updateNav(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {
1534 coff.updateNavInner(pt, nav_index) catch |err| switch (err) {1533 coff.updateNavInner(pt, nav_index) catch |err| switch (err) {
1535 error.OutOfMemory,1534 else => |e| return e,
1536 error.Overflow,1535 error.MappedFileIo => return coff.base.cgFail(nav_index, "linker failed to update variable: {t}", .{coff.mf.io_err.?}),
1537 error.RelocationNotByteAligned,
1538 => |e| return e,
1539 else => |e| return coff.base.cgFail(nav_index, "linker failed to update variable: {t}", .{e}),
1540 };1536 };
1541}1537}
1542fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {1538fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {
...@@ -1579,12 +1575,11 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde...@@ -1579,12 +1575,11 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
1579 codegen.generateSymbol(1575 codegen.generateSymbol(
1580 &coff.base,1576 &coff.base,
1581 pt,1577 pt,
1582 zcu.navSrcLoc(nav_index),
1583 .fromInterned(nav.resolved.?.value),1578 .fromInterned(nav.resolved.?.value),
1584 &nw.interface,1579 &nw.interface,
1585 .{ .atom_index = @enumFromInt(@intFromEnum(si)) },1580 .{ .atom_index = @enumFromInt(@intFromEnum(si)) },
1586 ) catch |err| switch (err) {1581 ) catch |err| switch (err) {
1587 error.WriteFailed => return error.OutOfMemory,1582 error.WriteFailed => return nw.err.?,
1588 else => |e| return e,1583 else => |e| return e,
1589 };1584 };
1590 si.get(coff).size = @intCast(nw.interface.end);1585 si.get(coff).size = @intCast(nw.interface.end);
...@@ -1615,8 +1610,7 @@ pub fn lowerUav(...@@ -1615,8 +1610,7 @@ pub fn lowerUav(
1615 pt: Zcu.PerThread,1610 pt: Zcu.PerThread,
1616 uav_val: InternPool.Index,1611 uav_val: InternPool.Index,
1617 uav_align: InternPool.Alignment,1612 uav_align: InternPool.Alignment,
1618 src_loc: Zcu.LazySrcLoc,1613) !link.File.SymbolId {
1619) !codegen.SymbolResult {
1620 const zcu = pt.zcu;1614 const zcu = pt.zcu;
1621 const gpa = zcu.gpa;1615 const gpa = zcu.gpa;
16221616
...@@ -1633,12 +1627,11 @@ pub fn lowerUav(...@@ -1633,12 +1627,11 @@ pub fn lowerUav(
1633 } else {1627 } else {
1634 gop.value_ptr.* = .{1628 gop.value_ptr.* = .{
1635 .alignment = uav_align,1629 .alignment = uav_align,
1636 .src_loc = src_loc,
1637 };1630 };
1638 coff.const_prog_node.increaseEstimatedTotalItems(1);1631 coff.const_prog_node.increaseEstimatedTotalItems(1);
1639 }1632 }
1640 }1633 }
1641 return .{ .sym_index = @enumFromInt(@intFromEnum(si)) };1634 return @enumFromInt(@intFromEnum(si));
1642}1635}
16431636
1644pub fn updateFunc(1637pub fn updateFunc(
...@@ -1648,15 +1641,11 @@ pub fn updateFunc(...@@ -1648,15 +1641,11 @@ pub fn updateFunc(
1648 mir: *const codegen.AnyMir,1641 mir: *const codegen.AnyMir,
1649) !void {1642) !void {
1650 coff.updateFuncInner(pt, func_index, mir) catch |err| switch (err) {1643 coff.updateFuncInner(pt, func_index, mir) catch |err| switch (err) {
1651 error.OutOfMemory,1644 else => |e| return e,
1652 error.Overflow,1645 error.MappedFileIo => return coff.base.cgFail(
1653 error.RelocationNotByteAligned,
1654 error.CodegenFail,
1655 => |e| return e,
1656 else => |e| return coff.base.cgFail(
1657 pt.zcu.funcInfo(func_index).owner_nav,1646 pt.zcu.funcInfo(func_index).owner_nav,
1658 "linker failed to update function: {s}",1647 "linker failed to update function: {t}",
1659 .{@errorName(e)},1648 .{coff.mf.io_err.?},
1660 ),1649 ),
1661 };1650 };
1662}1651}
...@@ -1714,7 +1703,6 @@ fn updateFuncInner(...@@ -1714,7 +1703,6 @@ fn updateFuncInner(
1714 codegen.emitFunction(1703 codegen.emitFunction(
1715 &coff.base,1704 &coff.base,
1716 pt,1705 pt,
1717 zcu.navSrcLoc(func.owner_nav),
1718 func_index,1706 func_index,
1719 @enumFromInt(@intFromEnum(si)),1707 @enumFromInt(@intFromEnum(si)),
1720 mir,1708 mir,
...@@ -1733,9 +1721,11 @@ pub fn updateErrorData(coff: *Coff, pt: Zcu.PerThread) !void {...@@ -1733,9 +1721,11 @@ pub fn updateErrorData(coff: *Coff, pt: Zcu.PerThread) !void {
1733 .kind = .const_data,1721 .kind = .const_data,
1734 .index = @intCast(coff.lazy.getPtr(.const_data).map.getIndex(.anyerror_type) orelse return),1722 .index = @intCast(coff.lazy.getPtr(.const_data).map.getIndex(.anyerror_type) orelse return),
1735 }) catch |err| switch (err) {1723 }) catch |err| switch (err) {
1736 error.OutOfMemory => |e| return e,1724 else => |e| return e,
1737 error.CodegenFail => return error.LinkFailure,1725 error.MappedFileIo => return coff.base.comp.link_diags.fail(
1738 else => |e| return coff.base.comp.link_diags.fail("updateErrorData failed {t}", .{e}),1726 "updateErrorData failed: {t}",
1727 .{coff.mf.io_err.?},
1728 ),
1739 };1729 };
1740}1730}
17411731
...@@ -1780,12 +1770,11 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {...@@ -1780,12 +1770,11 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
1780 .{ .zcu = comp.zcu.?, .tid = tid },1770 .{ .zcu = comp.zcu.?, .tid = tid },
1781 pending_uav.key,1771 pending_uav.key,
1782 pending_uav.value.alignment,1772 pending_uav.value.alignment,
1783 pending_uav.value.src_loc,
1784 ) catch |err| switch (err) {1773 ) catch |err| switch (err) {
1785 error.OutOfMemory => |e| return e,1774 else => |e| return e,
1786 else => |e| return comp.link_diags.fail(1775 error.MappedFileIo => return comp.link_diags.fail(
1787 "linker failed to lower constant: {t}",1776 "linker failed to lower constant: {t}",
1788 .{e},1777 .{coff.mf.io_err.?},
1789 ),1778 ),
1790 };1779 };
1791 break :task;1780 break :task;
...@@ -1800,10 +1789,10 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {...@@ -1800,10 +1789,10 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
1800 );1789 );
1801 defer sub_prog_node.end();1790 defer sub_prog_node.end();
1802 coff.flushGlobal(pt, gmi) catch |err| switch (err) {1791 coff.flushGlobal(pt, gmi) catch |err| switch (err) {
1803 error.OutOfMemory => |e| return e,1792 else => |e| return e,
1804 else => |e| return comp.link_diags.fail(1793 error.MappedFileIo => return comp.link_diags.fail(
1805 "linker failed to lower constant: {t}",1794 "linker failed to lower constant: {t}",
1806 .{e},1795 .{coff.mf.io_err.?},
1807 ),1796 ),
1808 };1797 };
1809 break :task;1798 break :task;
...@@ -1827,10 +1816,10 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {...@@ -1827,10 +1816,10 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
1827 );1816 );
1828 defer sub_prog_node.end();1817 defer sub_prog_node.end();
1829 coff.flushLazy(pt, lmr) catch |err| switch (err) {1818 coff.flushLazy(pt, lmr) catch |err| switch (err) {
1830 error.OutOfMemory => |e| return e,1819 else => |e| return e,
1831 else => |e| return comp.link_diags.fail(1820 error.MappedFileIo => return comp.link_diags.fail(
1832 "linker failed to lower lazy {s}: {t}",1821 "linker failed to lower lazy {s}: {t}",
1833 .{ kind, e },1822 .{ kind, coff.mf.io_err.? },
1834 ),1823 ),
1835 };1824 };
1836 break :task;1825 break :task;
...@@ -1885,7 +1874,6 @@ fn flushUav(...@@ -1885,7 +1874,6 @@ fn flushUav(
1885 pt: Zcu.PerThread,1874 pt: Zcu.PerThread,
1886 umi: Node.UavMapIndex,1875 umi: Node.UavMapIndex,
1887 uav_align: InternPool.Alignment,1876 uav_align: InternPool.Alignment,
1888 src_loc: Zcu.LazySrcLoc,
1889) !void {1877) !void {
1890 const zcu = pt.zcu;1878 const zcu = pt.zcu;
1891 const gpa = zcu.gpa;1879 const gpa = zcu.gpa;
...@@ -1928,12 +1916,11 @@ fn flushUav(...@@ -1928,12 +1916,11 @@ fn flushUav(
1928 codegen.generateSymbol(1916 codegen.generateSymbol(
1929 &coff.base,1917 &coff.base,
1930 pt,1918 pt,
1931 src_loc,
1932 .fromInterned(uav_val),1919 .fromInterned(uav_val),
1933 &nw.interface,1920 &nw.interface,
1934 .{ .atom_index = @enumFromInt(@intFromEnum(si)) },1921 .{ .atom_index = @enumFromInt(@intFromEnum(si)) },
1935 ) catch |err| switch (err) {1922 ) catch |err| switch (err) {
1936 error.WriteFailed => return error.OutOfMemory,1923 error.WriteFailed => return nw.err.?,
1937 else => |e| return e,1924 else => |e| return e,
1938 };1925 };
1939 si.get(coff).size = @intCast(nw.interface.end);1926 si.get(coff).size = @intCast(nw.interface.end);
...@@ -2139,16 +2126,18 @@ fn flushLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {...@@ -2139,16 +2126,18 @@ fn flushLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {
2139 var nw: MappedFile.Node.Writer = undefined;2126 var nw: MappedFile.Node.Writer = undefined;
2140 ni.writer(&coff.mf, gpa, &nw);2127 ni.writer(&coff.mf, gpa, &nw);
2141 defer nw.deinit();2128 defer nw.deinit();
2142 try codegen.generateLazySymbol(2129 codegen.generateLazySymbol(
2143 &coff.base,2130 &coff.base,
2144 pt,2131 pt,
2145 Type.fromInterned(lazy.ty).srcLocOrNull(pt.zcu) orelse .unneeded,
2146 lazy,2132 lazy,
2147 &required_alignment,2133 &required_alignment,
2148 &nw.interface,2134 &nw.interface,
2149 .none,2135 .none,
2150 .{ .atom_index = @enumFromInt(@intFromEnum(si)) },2136 .{ .atom_index = @enumFromInt(@intFromEnum(si)) },
2151 );2137 ) catch |err| switch (err) {
2138 error.WriteFailed => return nw.err.?,
2139 else => |e| return e,
2140 };
2152 si.get(coff).size = @intCast(nw.interface.end);2141 si.get(coff).size = @intCast(nw.interface.end);
2153 si.applyLocationRelocs(coff);2142 si.applyLocationRelocs(coff);
2154}2143}
...@@ -2314,17 +2303,6 @@ pub fn updateExports(...@@ -2314,17 +2303,6 @@ pub fn updateExports(
2314 pt: Zcu.PerThread,2303 pt: Zcu.PerThread,
2315 exported: Zcu.Exported,2304 exported: Zcu.Exported,
2316 export_indices: []const Zcu.Export.Index,2305 export_indices: []const Zcu.Export.Index,
2317) !void {
2318 return coff.updateExportsInner(pt, exported, export_indices) catch |err| switch (err) {
2319 error.OutOfMemory => error.OutOfMemory,
2320 error.LinkFailure => error.AnalysisFail,
2321 };
2322}
2323fn updateExportsInner(
2324 coff: *Coff,
2325 pt: Zcu.PerThread,
2326 exported: Zcu.Exported,
2327 export_indices: []const Zcu.Export.Index,
2328) !void {2306) !void {
2329 const zcu = pt.zcu;2307 const zcu = pt.zcu;
2330 const gpa = zcu.gpa;2308 const gpa = zcu.gpa;
...@@ -2340,18 +2318,11 @@ fn updateExportsInner(...@@ -2340,18 +2318,11 @@ fn updateExportsInner(
2340 try coff.symbol_table.ensureUnusedCapacity(gpa, export_indices.len);2318 try coff.symbol_table.ensureUnusedCapacity(gpa, export_indices.len);
2341 const exported_si: Symbol.Index = switch (exported) {2319 const exported_si: Symbol.Index = switch (exported) {
2342 .nav => |nav| try coff.navSymbol(zcu, nav),2320 .nav => |nav| try coff.navSymbol(zcu, nav),
2343 .uav => |uav| @enumFromInt(@intFromEnum(switch (try coff.lowerUav(2321 .uav => |uav| @enumFromInt(@intFromEnum(try coff.lowerUav(
2344 pt,2322 pt,
2345 uav,2323 uav,
2346 Type.fromInterned(ip.typeOf(uav)).abiAlignment(zcu),2324 Type.fromInterned(ip.typeOf(uav)).abiAlignment(zcu),
2347 export_indices[0].ptr(zcu).src,2325 ))),
2348 )) {
2349 .sym_index => |si| si,
2350 .fail => |em| {
2351 defer em.destroy(gpa);
2352 return coff.base.comp.link_diags.fail("{s}", .{em.msg});
2353 },
2354 })),
2355 };2326 };
2356 while (try coff.idle(pt.tid)) {}2327 while (try coff.idle(pt.tid)) {}
2357 const exported_ni = exported_si.node(coff);2328 const exported_ni = exported_si.node(coff);
src/link/Dwarf.zig+24-48
...@@ -51,21 +51,15 @@ pub const UpdateError = error{...@@ -51,21 +51,15 @@ pub const UpdateError = error{
51 Underflow,51 Underflow,
52 UnexpectedEndOfFile,52 UnexpectedEndOfFile,
53 NonResizable,53 NonResizable,
54 /// TODO why is this in the error set?54 Overflow,
55 ConnectionResetByPeer,
56 /// TODO why is this in the error set?
57 SocketUnconnected,
58} ||55} ||
59 codegen.GenerateSymbolError ||56 link.Error ||
60 Io.File.OpenError ||57 Io.File.OpenError ||
61 Io.File.LengthError ||58 Io.File.LengthError ||
62 Io.File.ReadPositionalError ||59 Io.File.ReadPositionalError ||
63 Io.File.WritePositionalError;60 Io.File.WritePositionalError;
6461
65pub const FlushError = UpdateError;62pub const RelocError = Io.File.PWriteError;
66
67pub const RelocError =
68 Io.File.PWriteError;
6963
70pub const AddressSize = enum(u8) {64pub const AddressSize = enum(u8) {
71 @"32" = 4,65 @"32" = 4,
...@@ -1579,19 +1573,17 @@ pub const WipNav = struct {...@@ -1579,19 +1573,17 @@ pub const WipNav = struct {
1579 pub const LocalConstTag = enum { comptime_arg, local_const };1573 pub const LocalConstTag = enum { comptime_arg, local_const };
1580 pub fn genLocalConstDebugInfo(1574 pub fn genLocalConstDebugInfo(
1581 wip_nav: *WipNav,1575 wip_nav: *WipNav,
1582 src_loc: Zcu.LazySrcLoc,
1583 tag: LocalConstTag,1576 tag: LocalConstTag,
1584 opt_name: ?[]const u8,1577 opt_name: ?[]const u8,
1585 val: Value,1578 val: Value,
1586 ) UpdateError!void {1579 ) UpdateError!void {
1587 return wip_nav.genLocalConstDebugInfoWriterError(src_loc, tag, opt_name, val) catch |err| switch (err) {1580 return wip_nav.genLocalConstDebugInfoWriterError(tag, opt_name, val) catch |err| switch (err) {
1588 error.WriteFailed => error.OutOfMemory,1581 error.WriteFailed => error.OutOfMemory,
1589 else => |e| e,1582 else => |e| e,
1590 };1583 };
1591 }1584 }
1592 fn genLocalConstDebugInfoWriterError(1585 fn genLocalConstDebugInfoWriterError(
1593 wip_nav: *WipNav,1586 wip_nav: *WipNav,
1594 src_loc: Zcu.LazySrcLoc,
1595 tag: LocalConstTag,1587 tag: LocalConstTag,
1596 opt_name: ?[]const u8,1588 opt_name: ?[]const u8,
1597 val: Value,1589 val: Value,
...@@ -1617,7 +1609,7 @@ pub const WipNav = struct {...@@ -1617,7 +1609,7 @@ pub const WipNav = struct {
1617 });1609 });
1618 if (opt_name) |name| try wip_nav.strp(name);1610 if (opt_name) |name| try wip_nav.strp(name);
1619 try wip_nav.refType(ty);1611 try wip_nav.refType(ty);
1620 if (has_runtime_bits) try wip_nav.blockValue(src_loc, val);1612 if (has_runtime_bits) try wip_nav.blockValue(val);
1621 if (has_comptime_state) try wip_nav.refValue(val);1613 if (has_comptime_state) try wip_nav.refValue(val);
1622 wip_nav.any_children = true;1614 wip_nav.any_children = true;
1623 }1615 }
...@@ -2106,7 +2098,6 @@ pub const WipNav = struct {...@@ -2106,7 +2098,6 @@ pub const WipNav = struct {
21062098
2107 fn blockValue(2099 fn blockValue(
2108 wip_nav: *WipNav,2100 wip_nav: *WipNav,
2109 src_loc: Zcu.LazySrcLoc,
2110 val: Value,2101 val: Value,
2111 ) (UpdateError || Writer.Error)!void {2102 ) (UpdateError || Writer.Error)!void {
2112 const ty = val.typeOf(wip_nav.pt.zcu);2103 const ty = val.typeOf(wip_nav.pt.zcu);
...@@ -2118,7 +2109,6 @@ pub const WipNav = struct {...@@ -2118,7 +2109,6 @@ pub const WipNav = struct {
2118 try codegen.generateSymbol(2109 try codegen.generateSymbol(
2119 wip_nav.dwarf.bin_file,2110 wip_nav.dwarf.bin_file,
2120 wip_nav.pt,2111 wip_nav.pt,
2121 src_loc,
2122 val,2112 val,
2123 &wip_nav.debug_info.writer,2113 &wip_nav.debug_info.writer,
2124 .{ .debug_output = .{ .dwarf = wip_nav } },2114 .{ .debug_output = .{ .dwarf = wip_nav } },
...@@ -2592,7 +2582,7 @@ pub fn initWipNav(...@@ -2592,7 +2582,7 @@ pub fn initWipNav(
2592 pt: Zcu.PerThread,2582 pt: Zcu.PerThread,
2593 nav_index: InternPool.Nav.Index,2583 nav_index: InternPool.Nav.Index,
2594 sym_index: link.File.SymbolId,2584 sym_index: link.File.SymbolId,
2595) error{ OutOfMemory, CodegenFail }!WipNav {2585) error{ OutOfMemory, AlreadyReported }!WipNav {
2596 return initWipNavInner(dwarf, pt, nav_index, sym_index) catch |err| switch (err) {2586 return initWipNavInner(dwarf, pt, nav_index, sym_index) catch |err| switch (err) {
2597 error.OutOfMemory => error.OutOfMemory,2587 error.OutOfMemory => error.OutOfMemory,
2598 else => |e| pt.zcu.codegenFail(nav_index, "failed to init dwarf: {s}", .{@errorName(e)}),2588 else => |e| pt.zcu.codegenFail(nav_index, "failed to init dwarf: {s}", .{@errorName(e)}),
...@@ -3017,7 +3007,7 @@ fn finishWipNavWriterError(...@@ -3017,7 +3007,7 @@ fn finishWipNavWriterError(
3017 try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf });3007 try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf });
3018}3008}
30193009
3020pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error{ OutOfMemory, CodegenFail }!void {3010pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error{ OutOfMemory, AlreadyReported }!void {
3021 return updateComptimeNavInner(dwarf, pt, nav_index) catch |err| switch (err) {3011 return updateComptimeNavInner(dwarf, pt, nav_index) catch |err| switch (err) {
3022 error.OutOfMemory => error.OutOfMemory,3012 error.OutOfMemory => error.OutOfMemory,
3023 else => |e| pt.zcu.codegenFail(nav_index, "failed to update dwarf: {s}", .{@errorName(e)}),3013 else => |e| pt.zcu.codegenFail(nav_index, "failed to update dwarf: {s}", .{@errorName(e)}),
...@@ -3027,7 +3017,6 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool...@@ -3027,7 +3017,6 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
3027fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {3017fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {
3028 const zcu = pt.zcu;3018 const zcu = pt.zcu;
3029 const ip = &zcu.intern_pool;3019 const ip = &zcu.intern_pool;
3030 const nav_src_loc = zcu.navSrcLoc(nav_index);
30313020
3032 const nav = ip.getNav(nav_index);3021 const nav = ip.getNav(nav_index);
3033 const inst_info = nav.srcInst(ip).resolveFull(ip).?;3022 const inst_info = nav.srcInst(ip).resolveFull(ip).?;
...@@ -3207,7 +3196,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -3207,7 +3196,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
3207 }.toSlice(ip));3196 }.toSlice(ip));
3208 const nav_ty = nav_val.typeOf(zcu);3197 const nav_ty = nav_val.typeOf(zcu);
3209 try wip_nav.refType(nav_ty);3198 try wip_nav.refType(nav_ty);
3210 try wip_nav.blockValue(nav_src_loc, nav_val);3199 try wip_nav.blockValue(nav_val);
3211 try diw.writeUleb128(nav.resolved.?.@"align".toByteUnits() orelse3200 try diw.writeUleb128(nav.resolved.?.@"align".toByteUnits() orelse
3212 nav_ty.abiAlignment(zcu).toByteUnits().?);3201 nav_ty.abiAlignment(zcu).toByteUnits().?);
3213 try diw.writeByte(@intFromBool(decl.linkage != .normal));3202 try diw.writeByte(@intFromBool(decl.linkage != .normal));
...@@ -3241,7 +3230,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -3241,7 +3230,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
3241 try diw.writeUleb128(nav.resolved.?.@"align".toByteUnits() orelse3230 try diw.writeUleb128(nav.resolved.?.@"align".toByteUnits() orelse
3242 nav_ty.abiAlignment(zcu).toByteUnits().?);3231 nav_ty.abiAlignment(zcu).toByteUnits().?);
3243 try diw.writeByte(@intFromBool(decl.linkage != .normal));3232 try diw.writeByte(@intFromBool(decl.linkage != .normal));
3244 if (has_runtime_bits) try wip_nav.blockValue(nav_src_loc, nav_val);3233 if (has_runtime_bits) try wip_nav.blockValue(nav_val);
3245 if (has_comptime_state) try wip_nav.refValue(nav_val);3234 if (has_comptime_state) try wip_nav.refValue(nav_val);
3246 wip_nav.finishForward(nav_ty_reloc_index);3235 wip_nav.finishForward(nav_ty_reloc_index);
3247 try wip_nav.abbrevCode(.is_const);3236 try wip_nav.abbrevCode(.is_const);
...@@ -3551,19 +3540,6 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co...@@ -3551,19 +3540,6 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
3551 };3540 };
3552 defer wip_nav.deinit();3541 defer wip_nav.deinit();
35533542
3554 // TODO: we really shouldn't need source locations at this point in the pipeline: we've lost
3555 // that information by now. If the linker fundamentally cannot lower certain values, that needs
3556 // to be caught in the frontend; if it can only hit transient failures, they should be reported
3557 // without trying to tie them to a bogus source location.
3558 const src_loc: Zcu.LazySrcLoc = .{
3559 .base_node_inst = inst: {
3560 const mod_root_file_index = zcu.module_roots.get(zcu.std_mod).?.unwrap().?;
3561 const mod_root_type_index = zcu.fileRootType(mod_root_file_index);
3562 break :inst ip.loadStructType(mod_root_type_index).zir_index;
3563 },
3564 .offset = .{ .byte_abs = 0 },
3565 };
3566
3567 const diw = &wip_nav.debug_info.writer;3543 const diw = &wip_nav.debug_info.writer;
3568 var big_int_space: Value.BigIntSpace = undefined;3544 var big_int_space: Value.BigIntSpace = undefined;
3569 switch (value_ip_key) {3545 switch (value_ip_key) {
...@@ -3588,7 +3564,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co...@@ -3588,7 +3564,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
3588 else => if (ptr_type.sentinel == .none) .ptr_aligned_type else .ptr_aligned_sentinel_type,3564 else => if (ptr_type.sentinel == .none) .ptr_aligned_type else .ptr_aligned_sentinel_type,
3589 });3565 });
3590 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});3566 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
3591 if (ptr_type.sentinel != .none) try wip_nav.blockValue(src_loc, .fromInterned(ptr_type.sentinel));3567 if (ptr_type.sentinel != .none) try wip_nav.blockValue(.fromInterned(ptr_type.sentinel));
3592 if (ptr_type.flags.alignment.toByteUnits()) |a| try diw.writeUleb128(a);3568 if (ptr_type.flags.alignment.toByteUnits()) |a| try diw.writeUleb128(a);
3593 try diw.writeByte(@intFromEnum(ptr_type.flags.address_space));3569 try diw.writeByte(@intFromEnum(ptr_type.flags.address_space));
3594 if (ptr_type.flags.is_const or ptr_type.flags.is_volatile) try wip_nav.infoSectionOffset(3570 if (ptr_type.flags.is_const or ptr_type.flags.is_volatile) try wip_nav.infoSectionOffset(
...@@ -3633,7 +3609,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co...@@ -3633,7 +3609,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
3633 const array_child_type: Type = .fromInterned(array_type.child);3609 const array_child_type: Type = .fromInterned(array_type.child);
3634 try wip_nav.abbrevCode(if (array_type.sentinel == .none) .array_type else .array_sentinel_type);3610 try wip_nav.abbrevCode(if (array_type.sentinel == .none) .array_type else .array_sentinel_type);
3635 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});3611 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
3636 if (array_type.sentinel != .none) try wip_nav.blockValue(src_loc, .fromInterned(array_type.sentinel));3612 if (array_type.sentinel != .none) try wip_nav.blockValue(.fromInterned(array_type.sentinel));
3637 try wip_nav.refType(array_child_type);3613 try wip_nav.refType(array_child_type);
3638 try wip_nav.abbrevCode(.array_len);3614 try wip_nav.abbrevCode(.array_len);
3639 try wip_nav.refType(.usize);3615 try wip_nav.refType(.usize);
...@@ -3880,7 +3856,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co...@@ -3880,7 +3856,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
3880 if (has_comptime_state)3856 if (has_comptime_state)
3881 try wip_nav.refValue(.fromInterned(comptime_value))3857 try wip_nav.refValue(.fromInterned(comptime_value))
3882 else if (has_runtime_bits)3858 else if (has_runtime_bits)
3883 try wip_nav.blockValue(src_loc, .fromInterned(comptime_value));3859 try wip_nav.blockValue(.fromInterned(comptime_value));
3884 }3860 }
3885 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));3861 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
3886 },3862 },
...@@ -3967,7 +3943,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co...@@ -3967,7 +3943,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
3967 if (has_comptime_state)3943 if (has_comptime_state)
3968 try wip_nav.refValue(.fromInterned(field_init))3944 try wip_nav.refValue(.fromInterned(field_init))
3969 else if (has_runtime_bits)3945 else if (has_runtime_bits)
3970 try wip_nav.blockValue(ty.srcLoc(zcu), .fromInterned(field_init));3946 try wip_nav.blockValue(.fromInterned(field_init));
3971 }3947 }
3972 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));3948 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
3973 }3949 }
...@@ -4332,7 +4308,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co...@@ -4332,7 +4308,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
4332 if (has_comptime_state)4308 if (has_comptime_state)
4333 try wip_nav.refValue(.fromInterned(payload_val))4309 try wip_nav.refValue(.fromInterned(payload_val))
4334 else4310 else
4335 try wip_nav.blockValue(src_loc, .fromInterned(payload_val));4311 try wip_nav.blockValue(.fromInterned(payload_val));
4336 },4312 },
4337 }4313 }
4338 {4314 {
...@@ -4500,7 +4476,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co...@@ -4500,7 +4476,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
4500 {4476 {
4501 try wip_nav.abbrevCode(.comptime_value_field_runtime_bits);4477 try wip_nav.abbrevCode(.comptime_value_field_runtime_bits);
4502 try wip_nav.strp("len");4478 try wip_nav.strp("len");
4503 try wip_nav.blockValue(src_loc, .fromInterned(slice.len));4479 try wip_nav.blockValue(.fromInterned(slice.len));
4504 }4480 }
4505 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));4481 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
4506 },4482 },
...@@ -4513,8 +4489,8 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co...@@ -4513,8 +4489,8 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
4513 try wip_nav.strp("has_value");4489 try wip_nav.strp("has_value");
4514 switch (optRepr(opt_child_type, zcu)) {4490 switch (optRepr(opt_child_type, zcu)) {
4515 .opv_null => try diw.writeUleb128(0),4491 .opv_null => try diw.writeUleb128(0),
4516 .unpacked => try wip_nav.blockValue(src_loc, .makeBool(opt.val != .none)),4492 .unpacked => try wip_nav.blockValue(.makeBool(opt.val != .none)),
4517 .error_set, .pointer => try wip_nav.blockValue(src_loc, .fromInterned(value_index)),4493 .error_set, .pointer => try wip_nav.blockValue(.fromInterned(value_index)),
4518 }4494 }
4519 }4495 }
4520 if (opt.val != .none) child_field: {4496 if (opt.val != .none) child_field: {
...@@ -4530,7 +4506,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co...@@ -4530,7 +4506,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
4530 if (has_comptime_state)4506 if (has_comptime_state)
4531 try wip_nav.refValue(.fromInterned(opt.val))4507 try wip_nav.refValue(.fromInterned(opt.val))
4532 else4508 else
4533 try wip_nav.blockValue(src_loc, .fromInterned(opt.val));4509 try wip_nav.blockValue(.fromInterned(opt.val));
4534 }4510 }
4535 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));4511 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
4536 },4512 },
...@@ -4561,7 +4537,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co...@@ -4561,7 +4537,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
4561 if (has_comptime_state)4537 if (has_comptime_state)
4562 try wip_nav.refValue(field_value)4538 try wip_nav.refValue(field_value)
4563 else4539 else
4564 try wip_nav.blockValue(src_loc, field_value);4540 try wip_nav.blockValue(field_value);
4565 }4541 }
4566 },4542 },
4567 .tuple_type => |tuple_type| for (0..tuple_type.types.len) |field_index| {4543 .tuple_type => |tuple_type| for (0..tuple_type.types.len) |field_index| {
...@@ -4588,7 +4564,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co...@@ -4588,7 +4564,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
4588 if (has_comptime_state)4564 if (has_comptime_state)
4589 try wip_nav.refValue(field_value)4565 try wip_nav.refValue(field_value)
4590 else4566 else
4591 try wip_nav.blockValue(src_loc, field_value);4567 try wip_nav.blockValue(field_value);
4592 },4568 },
4593 inline .array_type, .vector_type => |sequence_type| {4569 inline .array_type, .vector_type => |sequence_type| {
4594 const child_type: Type = .fromInterned(sequence_type.child);4570 const child_type: Type = .fromInterned(sequence_type.child);
...@@ -4608,7 +4584,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co...@@ -4608,7 +4584,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
4608 if (has_comptime_state)4584 if (has_comptime_state)
4609 try wip_nav.refValue(.fromInterned(elem))4585 try wip_nav.refValue(.fromInterned(elem))
4610 else4586 else
4611 try wip_nav.blockValue(src_loc, .fromInterned(elem));4587 try wip_nav.blockValue(.fromInterned(elem));
4612 }4588 }
4613 },4589 },
4614 else => unreachable,4590 else => unreachable,
...@@ -4636,7 +4612,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co...@@ -4636,7 +4612,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
4636 if (has_comptime_state)4612 if (has_comptime_state)
4637 try wip_nav.refValue(.fromInterned(un.val))4613 try wip_nav.refValue(.fromInterned(un.val))
4638 else4614 else
4639 try wip_nav.blockValue(src_loc, .fromInterned(un.val));4615 try wip_nav.blockValue(.fromInterned(un.val));
4640 }4616 }
4641 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));4617 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
4642 },4618 },
...@@ -4708,13 +4684,13 @@ fn refAbbrevCode(...@@ -4708,13 +4684,13 @@ fn refAbbrevCode(
4708 return @intFromEnum(abbrev_code);4684 return @intFromEnum(abbrev_code);
4709}4685}
47104686
4711pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {4687pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) UpdateError!void {
4712 return dwarf.flushWriterError(pt) catch |err| switch (err) {4688 return dwarf.flushWriterError(pt) catch |err| switch (err) {
4713 error.WriteFailed => error.OutOfMemory,4689 error.WriteFailed => error.OutOfMemory,
4714 else => |e| e,4690 else => |e| e,
4715 };4691 };
4716}4692}
4717fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (FlushError || Writer.Error)!void {4693fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (UpdateError || Writer.Error)!void {
4718 const zcu = pt.zcu;4694 const zcu = pt.zcu;
4719 const ip = &zcu.intern_pool;4695 const ip = &zcu.intern_pool;
4720 const comp = dwarf.bin_file.comp;4696 const comp = dwarf.bin_file.comp;
src/link/Elf.zig+32-33
...@@ -476,9 +476,8 @@ pub fn lowerUav(...@@ -476,9 +476,8 @@ pub fn lowerUav(
476 pt: Zcu.PerThread,476 pt: Zcu.PerThread,
477 uav: InternPool.Index,477 uav: InternPool.Index,
478 explicit_alignment: InternPool.Alignment,478 explicit_alignment: InternPool.Alignment,
479 src_loc: Zcu.LazySrcLoc,479) !link.File.SymbolId {
480) !codegen.SymbolResult {480 return self.zigObjectPtr().?.lowerUav(self, pt, uav, explicit_alignment);
481 return self.zigObjectPtr().?.lowerUav(self, pt, uav, explicit_alignment, src_loc);
482}481}
483482
484pub fn getUavVAddr(self: *Elf, uav: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {483pub fn getUavVAddr(self: *Elf, uav: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {
...@@ -743,7 +742,7 @@ pub fn loadInput(self: *Elf, input: link.Input) !void {...@@ -743,7 +742,7 @@ pub fn loadInput(self: *Elf, input: link.Input) !void {
743 }742 }
744}743}
745744
746pub fn flush(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {745pub fn flush(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.Error!void {
747 const tracy = trace(@src());746 const tracy = trace(@src());
748 defer tracy.end();747 defer tracy.end();
749748
...@@ -757,7 +756,7 @@ pub fn flush(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std...@@ -757,7 +756,7 @@ pub fn flush(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std
757 defer sub_prog_node.end();756 defer sub_prog_node.end();
758757
759 return flushInner(self, arena, tid) catch |err| switch (err) {758 return flushInner(self, arena, tid) catch |err| switch (err) {
760 error.OutOfMemory, error.LinkFailure => |e| return e,759 error.OutOfMemory, error.AlreadyReported => |e| return e,
761 else => |e| return diags.fail("ELF flush failed: {t}", .{e}),760 else => |e| return diags.fail("ELF flush failed: {t}", .{e}),
762 };761 };
763}762}
...@@ -784,7 +783,7 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {...@@ -784,7 +783,7 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
784 .Exe => {},783 .Exe => {},
785 }784 }
786785
787 if (diags.hasErrors()) return error.LinkFailure;786 if (diags.hasErrors()) return error.AlreadyReported;
788787
789 // If we haven't already, create a linker-generated input file comprising of788 // If we haven't already, create a linker-generated input file comprising of
790 // linker-defined synthetic symbols only such as `_DYNAMIC`, etc.789 // linker-defined synthetic symbols only such as `_DYNAMIC`, etc.
...@@ -816,7 +815,7 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {...@@ -816,7 +815,7 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
816 }815 }
817816
818 self.checkDuplicates() catch |err| switch (err) {817 self.checkDuplicates() catch |err| switch (err) {
819 error.HasDuplicates => return error.LinkFailure,818 error.HasDuplicates => return error.AlreadyReported,
820 else => |e| return e,819 else => |e| return e,
821 };820 };
822821
...@@ -903,7 +902,7 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {...@@ -903,7 +902,7 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
903 error.RelocFailure, error.RelaxFailure => has_reloc_errors = true,902 error.RelocFailure, error.RelaxFailure => has_reloc_errors = true,
904 error.UnsupportedCpuArch => {903 error.UnsupportedCpuArch => {
905 try self.reportUnsupportedCpuArch();904 try self.reportUnsupportedCpuArch();
906 return error.LinkFailure;905 return error.AlreadyReported;
907 },906 },
908 else => |e| return e,907 else => |e| return e,
909 };908 };
...@@ -912,7 +911,7 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {...@@ -912,7 +911,7 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
912911
913 try self.reportUndefinedSymbols(&undefs);912 try self.reportUndefinedSymbols(&undefs);
914913
915 if (has_reloc_errors) return error.LinkFailure;914 if (has_reloc_errors) return error.AlreadyReported;
916 }915 }
917916
918 try self.writePhdrTable();917 try self.writePhdrTable();
...@@ -921,10 +920,10 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {...@@ -921,10 +920,10 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
921 try self.writeMergeSections();920 try self.writeMergeSections();
922921
923 self.writeSyntheticSections() catch |err| switch (err) {922 self.writeSyntheticSections() catch |err| switch (err) {
924 error.RelocFailure => return error.LinkFailure,923 error.RelocFailure => return error.AlreadyReported,
925 error.UnsupportedCpuArch => {924 error.UnsupportedCpuArch => {
926 try self.reportUnsupportedCpuArch();925 try self.reportUnsupportedCpuArch();
927 return error.LinkFailure;926 return error.AlreadyReported;
928 },927 },
929 else => |e| return e,928 else => |e| return e,
930 };929 };
...@@ -938,7 +937,7 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {...@@ -938,7 +937,7 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
938 try self.writeElfHeader();937 try self.writeElfHeader();
939 }938 }
940939
941 if (diags.hasErrors()) return error.LinkFailure;940 if (diags.hasErrors()) return error.AlreadyReported;
942}941}
943942
944fn dumpArgvInit(self: *Elf, arena: Allocator) !void {943fn dumpArgvInit(self: *Elf, arena: Allocator) !void {
...@@ -1053,7 +1052,7 @@ pub fn openParseObjectReportingFailure(self: *Elf, path: Path) void {...@@ -1053,7 +1052,7 @@ pub fn openParseObjectReportingFailure(self: *Elf, path: Path) void {
1053 const diags = &comp.link_diags;1052 const diags = &comp.link_diags;
1054 const obj = link.openObject(io, path, false, false) catch |err| {1053 const obj = link.openObject(io, path, false, false) catch |err| {
1055 switch (diags.failParse(path, "failed to open object: {t}", .{err})) {1054 switch (diags.failParse(path, "failed to open object: {t}", .{err})) {
1056 error.LinkFailure => return,1055 error.AlreadyReported => return,
1057 }1056 }
1058 };1057 };
1059 self.parseObjectReportingFailure(obj);1058 self.parseObjectReportingFailure(obj);
...@@ -1063,7 +1062,7 @@ fn parseObjectReportingFailure(self: *Elf, obj: link.Input.Object) void {...@@ -1063,7 +1062,7 @@ fn parseObjectReportingFailure(self: *Elf, obj: link.Input.Object) void {
1063 const comp = self.base.comp;1062 const comp = self.base.comp;
1064 const diags = &comp.link_diags;1063 const diags = &comp.link_diags;
1065 self.parseObject(obj) catch |err| switch (err) {1064 self.parseObject(obj) catch |err| switch (err) {
1066 error.LinkFailure => return, // already reported1065 error.AlreadyReported => return, // already reported
1067 else => |e| diags.addParseError(obj.path, "failed to parse object: {t}", .{e}),1066 else => |e| diags.addParseError(obj.path, "failed to parse object: {t}", .{e}),
1068 };1067 };
1069}1068}
...@@ -1343,7 +1342,7 @@ fn scanRelocs(self: *Elf) !void {...@@ -1343,7 +1342,7 @@ fn scanRelocs(self: *Elf) !void {
1343 error.RelaxFailure => unreachable,1342 error.RelaxFailure => unreachable,
1344 error.UnsupportedCpuArch => {1343 error.UnsupportedCpuArch => {
1345 try self.reportUnsupportedCpuArch();1344 try self.reportUnsupportedCpuArch();
1346 return error.LinkFailure;1345 return error.AlreadyReported;
1347 },1346 },
1348 error.RelocFailure => has_reloc_errors = true,1347 error.RelocFailure => has_reloc_errors = true,
1349 else => |e| return e,1348 else => |e| return e,
...@@ -1354,7 +1353,7 @@ fn scanRelocs(self: *Elf) !void {...@@ -1354,7 +1353,7 @@ fn scanRelocs(self: *Elf) !void {
1354 error.RelaxFailure => unreachable,1353 error.RelaxFailure => unreachable,
1355 error.UnsupportedCpuArch => {1354 error.UnsupportedCpuArch => {
1356 try self.reportUnsupportedCpuArch();1355 try self.reportUnsupportedCpuArch();
1357 return error.LinkFailure;1356 return error.AlreadyReported;
1358 },1357 },
1359 error.RelocFailure => has_reloc_errors = true,1358 error.RelocFailure => has_reloc_errors = true,
1360 else => |e| return e,1359 else => |e| return e,
...@@ -1363,7 +1362,7 @@ fn scanRelocs(self: *Elf) !void {...@@ -1363,7 +1362,7 @@ fn scanRelocs(self: *Elf) !void {
13631362
1364 try self.reportUndefinedSymbols(&undefs);1363 try self.reportUndefinedSymbols(&undefs);
13651364
1366 if (has_reloc_errors) return error.LinkFailure;1365 if (has_reloc_errors) return error.AlreadyReported;
13671366
1368 if (self.zigObjectPtr()) |zo| {1367 if (self.zigObjectPtr()) |zo| {
1369 try zo.asFile().createSymbolIndirection(self);1368 try zo.asFile().createSymbolIndirection(self);
...@@ -1690,7 +1689,7 @@ pub fn updateFunc(...@@ -1690,7 +1689,7 @@ pub fn updateFunc(
1690 pt: Zcu.PerThread,1689 pt: Zcu.PerThread,
1691 func_index: InternPool.Index,1690 func_index: InternPool.Index,
1692 mir: *const codegen.AnyMir,1691 mir: *const codegen.AnyMir,
1693) link.File.UpdateNavError!void {1692) link.Error!void {
1694 return self.zigObjectPtr().?.updateFunc(self, pt, func_index, mir);1693 return self.zigObjectPtr().?.updateFunc(self, pt, func_index, mir);
1695}1694}
16961695
...@@ -1698,7 +1697,7 @@ pub fn updateNav(...@@ -1698,7 +1697,7 @@ pub fn updateNav(
1698 self: *Elf,1697 self: *Elf,
1699 pt: Zcu.PerThread,1698 pt: Zcu.PerThread,
1700 nav: InternPool.Nav.Index,1699 nav: InternPool.Nav.Index,
1701) link.File.UpdateNavError!void {1700) link.Error!void {
1702 return self.zigObjectPtr().?.updateNav(self, pt, nav);1701 return self.zigObjectPtr().?.updateNav(self, pt, nav);
1703}1702}
17041703
...@@ -1707,7 +1706,7 @@ pub fn updateContainerType(...@@ -1707,7 +1706,7 @@ pub fn updateContainerType(
1707 pt: Zcu.PerThread,1706 pt: Zcu.PerThread,
1708 ty: InternPool.Index,1707 ty: InternPool.Index,
1709 success: bool,1708 success: bool,
1710) link.File.UpdateContainerTypeError!void {1709) link.Error!void {
1711 return self.zigObjectPtr().?.updateContainerType(pt, ty, success) catch |err| switch (err) {1710 return self.zigObjectPtr().?.updateContainerType(pt, ty, success) catch |err| switch (err) {
1712 error.OutOfMemory => |e| return e,1711 error.OutOfMemory => |e| return e,
1713 };1712 };
...@@ -1718,11 +1717,11 @@ pub fn updateExports(...@@ -1718,11 +1717,11 @@ pub fn updateExports(
1718 pt: Zcu.PerThread,1717 pt: Zcu.PerThread,
1719 exported: Zcu.Exported,1718 exported: Zcu.Exported,
1720 export_indices: []const Zcu.Export.Index,1719 export_indices: []const Zcu.Export.Index,
1721) link.File.UpdateExportsError!void {1720) link.Error!void {
1722 return self.zigObjectPtr().?.updateExports(self, pt, exported, export_indices);1721 return self.zigObjectPtr().?.updateExports(self, pt, exported, export_indices);
1723}1722}
17241723
1725pub fn updateLineNumber(self: *Elf, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {1724pub fn updateLineNumber(self: *Elf, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) link.Error!void {
1726 return self.zigObjectPtr().?.updateLineNumber(pt, ti_id);1725 return self.zigObjectPtr().?.updateLineNumber(pt, ti_id);
1727}1726}
17281727
...@@ -1784,12 +1783,12 @@ pub fn resolveMergeSections(self: *Elf) !void {...@@ -1784,12 +1783,12 @@ pub fn resolveMergeSections(self: *Elf) !void {
1784 if (!object.alive) continue;1783 if (!object.alive) continue;
1785 if (!object.dirty) continue;1784 if (!object.dirty) continue;
1786 object.initInputMergeSections(self) catch |err| switch (err) {1785 object.initInputMergeSections(self) catch |err| switch (err) {
1787 error.LinkFailure => has_errors = true,1786 error.AlreadyReported => has_errors = true,
1788 else => |e| return e,1787 else => |e| return e,
1789 };1788 };
1790 }1789 }
17911790
1792 if (has_errors) return error.LinkFailure;1791 if (has_errors) return error.AlreadyReported;
17931792
1794 for (self.objects.items) |index| {1793 for (self.objects.items) |index| {
1795 const object = self.file(index).?.object;1794 const object = self.file(index).?.object;
...@@ -1803,12 +1802,12 @@ pub fn resolveMergeSections(self: *Elf) !void {...@@ -1803,12 +1802,12 @@ pub fn resolveMergeSections(self: *Elf) !void {
1803 if (!object.alive) continue;1802 if (!object.alive) continue;
1804 if (!object.dirty) continue;1803 if (!object.dirty) continue;
1805 object.resolveMergeSubsections(self) catch |err| switch (err) {1804 object.resolveMergeSubsections(self) catch |err| switch (err) {
1806 error.LinkFailure => has_errors = true,1805 error.AlreadyReported => has_errors = true,
1807 else => |e| return e,1806 else => |e| return e,
1808 };1807 };
1809 }1808 }
18101809
1811 if (has_errors) return error.LinkFailure;1810 if (has_errors) return error.AlreadyReported;
1812}1811}
18131812
1814pub fn finalizeMergeSections(self: *Elf) !void {1813pub fn finalizeMergeSections(self: *Elf) !void {
...@@ -2998,7 +2997,7 @@ fn writeAtoms(self: *Elf) !void {...@@ -2998,7 +2997,7 @@ fn writeAtoms(self: *Elf) !void {
2998 atom_list.write(&buffer, &undefs, self) catch |err| switch (err) {2997 atom_list.write(&buffer, &undefs, self) catch |err| switch (err) {
2999 error.UnsupportedCpuArch => {2998 error.UnsupportedCpuArch => {
3000 try self.reportUnsupportedCpuArch();2999 try self.reportUnsupportedCpuArch();
3001 return error.LinkFailure;3000 return error.AlreadyReported;
3002 },3001 },
3003 error.RelocFailure, error.RelaxFailure => has_reloc_errors = true,3002 error.RelocFailure, error.RelaxFailure => has_reloc_errors = true,
3004 else => |e| return e,3003 else => |e| return e,
...@@ -3006,7 +3005,7 @@ fn writeAtoms(self: *Elf) !void {...@@ -3006,7 +3005,7 @@ fn writeAtoms(self: *Elf) !void {
3006 }3005 }
30073006
3008 try self.reportUndefinedSymbols(&undefs);3007 try self.reportUndefinedSymbols(&undefs);
3009 if (has_reloc_errors) return error.LinkFailure;3008 if (has_reloc_errors) return error.AlreadyReported;
30103009
3011 if (self.requiresThunks()) {3010 if (self.requiresThunks()) {
3012 for (self.thunks.items) |th| {3011 for (self.thunks.items) |th| {
...@@ -3838,9 +3837,9 @@ pub fn failFile(...@@ -3838,9 +3837,9 @@ pub fn failFile(
3838 file_index: File.Index,3837 file_index: File.Index,
3839 comptime format: []const u8,3838 comptime format: []const u8,
3840 args: anytype,3839 args: anytype,
3841) error{ OutOfMemory, LinkFailure } {3840) error{ OutOfMemory, AlreadyReported } {
3842 try addFileError(self, file_index, format, args);3841 try addFileError(self, file_index, format, args);
3843 return error.LinkFailure;3842 return error.AlreadyReported;
3844}3843}
38453844
3846const FormatShdr = struct {3845const FormatShdr = struct {
...@@ -4409,7 +4408,7 @@ pub fn stringTableLookup(strtab: []const u8, off: u32) [:0]const u8 {...@@ -4409,7 +4408,7 @@ pub fn stringTableLookup(strtab: []const u8, off: u32) [:0]const u8 {
4409 return slice[0..mem.indexOfScalar(u8, slice, 0).? :0];4408 return slice[0..mem.indexOfScalar(u8, slice, 0).? :0];
4410}4409}
44114410
4412pub fn pwriteAll(elf_file: *Elf, bytes: []const u8, offset: u64) error{LinkFailure}!void {4411pub fn pwriteAll(elf_file: *Elf, bytes: []const u8, offset: u64) error{AlreadyReported}!void {
4413 const comp = elf_file.base.comp;4412 const comp = elf_file.base.comp;
4414 const io = comp.io;4413 const io = comp.io;
4415 const diags = &comp.link_diags;4414 const diags = &comp.link_diags;
...@@ -4417,7 +4416,7 @@ pub fn pwriteAll(elf_file: *Elf, bytes: []const u8, offset: u64) error{LinkFailu...@@ -4417,7 +4416,7 @@ pub fn pwriteAll(elf_file: *Elf, bytes: []const u8, offset: u64) error{LinkFailu
4417 return diags.fail("failed to write: {t}", .{err});4416 return diags.fail("failed to write: {t}", .{err});
4418}4417}
44194418
4420pub fn setLength(elf_file: *Elf, length: u64) error{LinkFailure}!void {4419pub fn setLength(elf_file: *Elf, length: u64) error{AlreadyReported}!void {
4421 const comp = elf_file.base.comp;4420 const comp = elf_file.base.comp;
4422 const io = comp.i;4421 const io = comp.i;
4423 const diags = &comp.link_diags;4422 const diags = &comp.link_diags;
...@@ -4426,7 +4425,7 @@ pub fn setLength(elf_file: *Elf, length: u64) error{LinkFailure}!void {...@@ -4426,7 +4425,7 @@ pub fn setLength(elf_file: *Elf, length: u64) error{LinkFailure}!void {
4426 };4425 };
4427}4426}
44284427
4429pub fn cast(elf_file: *Elf, comptime T: type, x: anytype) error{LinkFailure}!T {4428pub fn cast(elf_file: *Elf, comptime T: type, x: anytype) error{AlreadyReported}!T {
4430 return std.math.cast(T, x) orelse {4429 return std.math.cast(T, x) orelse {
4431 const comp = elf_file.base.comp;4430 const comp = elf_file.base.comp;
4432 const diags = &comp.link_diags;4431 const diags = &comp.link_diags;
src/link/Elf/Object.zig+6-6
...@@ -282,7 +282,7 @@ pub fn validateEFlags(...@@ -282,7 +282,7 @@ pub fn validateEFlags(
282 );282 );
283 }283 }
284284
285 if (any_errors) return error.LinkFailure;285 if (any_errors) return error.AlreadyReported;
286 },286 },
287 else => {},287 else => {},
288 }288 }
...@@ -829,7 +829,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void {...@@ -829,7 +829,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void {
829 var err = try diags.addErrorWithNotes(1);829 var err = try diags.addErrorWithNotes(1);
830 try err.addMsg("string not null terminated", .{});830 try err.addMsg("string not null terminated", .{});
831 err.addNote("in {f}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });831 err.addNote("in {f}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });
832 return error.LinkFailure;832 return error.AlreadyReported;
833 }833 }
834 end += sh_entsize;834 end += sh_entsize;
835 const string = data[start..end];835 const string = data[start..end];
...@@ -844,7 +844,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void {...@@ -844,7 +844,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void {
844 var err = try diags.addErrorWithNotes(1);844 var err = try diags.addErrorWithNotes(1);
845 try err.addMsg("size not a multiple of sh_entsize", .{});845 try err.addMsg("size not a multiple of sh_entsize", .{});
846 err.addNote("in {f}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });846 err.addNote("in {f}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });
847 return error.LinkFailure;847 return error.AlreadyReported;
848 }848 }
849849
850 var pos: u32 = 0;850 var pos: u32 = 0;
...@@ -873,7 +873,7 @@ pub fn initOutputMergeSections(self: *Object, elf_file: *Elf) !void {...@@ -873,7 +873,7 @@ pub fn initOutputMergeSections(self: *Object, elf_file: *Elf) !void {
873}873}
874874
875pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{875pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{
876 LinkFailure,876 AlreadyReported,
877 OutOfMemory,877 OutOfMemory,
878 /// TODO report the error and remove this878 /// TODO report the error and remove this
879 Overflow,879 Overflow,
...@@ -925,7 +925,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{...@@ -925,7 +925,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{
925 try err.addMsg("invalid symbol value: {x}", .{esym.st_value});925 try err.addMsg("invalid symbol value: {x}", .{esym.st_value});
926 err.addNote("for symbol {s}", .{sym.name(elf_file)});926 err.addNote("for symbol {s}", .{sym.name(elf_file)});
927 err.addNote("in {f}", .{self.fmtPath()});927 err.addNote("in {f}", .{self.fmtPath()});
928 return error.LinkFailure;928 return error.AlreadyReported;
929 };929 };
930930
931 sym.ref = .{ .index = res.msub_index, .file = imsec.merge_section_index };931 sym.ref = .{ .index = res.msub_index, .file = imsec.merge_section_index };
...@@ -950,7 +950,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{...@@ -950,7 +950,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{
950 var err = try diags.addErrorWithNotes(1);950 var err = try diags.addErrorWithNotes(1);
951 try err.addMsg("invalid relocation at offset 0x{x}", .{rel.r_offset});951 try err.addMsg("invalid relocation at offset 0x{x}", .{rel.r_offset});
952 err.addNote("in {f}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });952 err.addNote("in {f}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });
953 return error.LinkFailure;953 return error.AlreadyReported;
954 };954 };
955955
956 const sym_index = try self.addSymbol(gpa);956 const sym_index = try self.addSymbol(gpa);
src/link/Elf/ZigObject.zig+28-57
...@@ -272,24 +272,18 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void {...@@ -272,24 +272,18 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void {
272272
273 // Most lazy symbols can be updated on first use, but273 // Most lazy symbols can be updated on first use, but
274 // anyerror needs to wait for everything to be flushed.274 // anyerror needs to wait for everything to be flushed.
275 if (metadata.text_state != .unused) self.updateLazySymbol(275 if (metadata.text_state != .unused) try self.updateLazySymbol(
276 elf_file,276 elf_file,
277 pt,277 pt,
278 .{ .kind = .code, .ty = .anyerror_type },278 .{ .kind = .code, .ty = .anyerror_type },
279 metadata.text_symbol_index,279 metadata.text_symbol_index,
280 ) catch |err| switch (err) {280 );
281 error.CodegenFail => return error.LinkFailure,281 if (metadata.rodata_state != .unused) try self.updateLazySymbol(
282 else => |e| return e,
283 };
284 if (metadata.rodata_state != .unused) self.updateLazySymbol(
285 elf_file,282 elf_file,
286 pt,283 pt,
287 .{ .kind = .const_data, .ty = .anyerror_type },284 .{ .kind = .const_data, .ty = .anyerror_type },
288 metadata.rodata_symbol_index,285 metadata.rodata_symbol_index,
289 ) catch |err| switch (err) {286 );
290 error.CodegenFail => return error.LinkFailure,
291 else => |e| return e,
292 };
293 }287 }
294 for (self.lazy_syms.values()) |*metadata| {288 for (self.lazy_syms.values()) |*metadata| {
295 if (metadata.text_state != .unused) metadata.text_state = .flushed;289 if (metadata.text_state != .unused) metadata.text_state = .flushed;
...@@ -999,8 +993,7 @@ pub fn lowerUav(...@@ -999,8 +993,7 @@ pub fn lowerUav(
999 pt: Zcu.PerThread,993 pt: Zcu.PerThread,
1000 uav: InternPool.Index,994 uav: InternPool.Index,
1001 explicit_alignment: InternPool.Alignment,995 explicit_alignment: InternPool.Alignment,
1002 src_loc: Zcu.LazySrcLoc,996) !link.File.SymbolId {
1003) !codegen.SymbolResult {
1004 const zcu = pt.zcu;997 const zcu = pt.zcu;
1005 const gpa = zcu.gpa;998 const gpa = zcu.gpa;
1006 const val = Value.fromInterned(uav);999 const val = Value.fromInterned(uav);
...@@ -1013,7 +1006,7 @@ pub fn lowerUav(...@@ -1013,7 +1006,7 @@ pub fn lowerUav(
1013 const sym = self.symbol(metadata.symbol_index);1006 const sym = self.symbol(metadata.symbol_index);
1014 const existing_alignment = sym.atom(elf_file).?.alignment;1007 const existing_alignment = sym.atom(elf_file).?.alignment;
1015 if (uav_alignment.order(existing_alignment).compare(.lte))1008 if (uav_alignment.order(existing_alignment).compare(.lte))
1016 return .{ .sym_index = @enumFromInt(metadata.symbol_index) };1009 return @enumFromInt(metadata.symbol_index);
1017 }1010 }
10181011
1019 const osec = if (self.data_relro_index) |sym_index|1012 const osec = if (self.data_relro_index) |sym_index|
...@@ -1033,31 +1026,25 @@ pub fn lowerUav(...@@ -1033,31 +1026,25 @@ pub fn lowerUav(
1033 const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{1026 const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{
1034 @intFromEnum(uav),1027 @intFromEnum(uav),
1035 }) catch unreachable;1028 }) catch unreachable;
1036 const res = self.lowerConst(1029 const sym_index = self.lowerConst(
1037 elf_file,1030 elf_file,
1038 pt,1031 pt,
1039 name,1032 name,
1040 val,1033 val,
1041 uav_alignment,1034 uav_alignment,
1042 osec,1035 osec,
1043 src_loc,
1044 ) catch |err| switch (err) {1036 ) catch |err| switch (err) {
1045 error.OutOfMemory => |e| return e,1037 error.OutOfMemory => |e| return e,
1046 else => |e| return .{ .fail = try Zcu.ErrorMsg.create(1038 else => |e| return elf_file.base.comp.link_diags.fail(
1047 gpa,1039 "failed to lower constant value: {t}",
1048 src_loc,1040 .{e},
1049 "unable to lower constant value: {s}",1041 ),
1050 .{@errorName(e)},
1051 ) },
1052 };1042 };
1053 switch (res) {1043 try self.uavs.put(gpa, uav, .{
1054 .sym_index => |sym_index| try self.uavs.put(gpa, uav, .{1044 .symbol_index = @intFromEnum(sym_index),
1055 .symbol_index = @intFromEnum(sym_index),1045 .allocated = true,
1056 .allocated = true,1046 });
1057 }),1047 return sym_index;
1058 .fail => {},
1059 }
1060 return res;
1061}1048}
10621049
1063pub fn getOrCreateMetadataForLazySymbol(1050pub fn getOrCreateMetadataForLazySymbol(
...@@ -1370,7 +1357,7 @@ fn updateNavCode(...@@ -1370,7 +1357,7 @@ fn updateNavCode(
1370 shdr_index: u32,1357 shdr_index: u32,
1371 code: []const u8,1358 code: []const u8,
1372 stt_bits: u8,1359 stt_bits: u8,
1373) link.File.UpdateNavError!void {1360) link.Error!void {
1374 const zcu = pt.zcu;1361 const zcu = pt.zcu;
1375 const gpa = zcu.gpa;1362 const gpa = zcu.gpa;
1376 const comp = elf_file.base.comp;1363 const comp = elf_file.base.comp;
...@@ -1473,7 +1460,7 @@ fn updateTlv(...@@ -1473,7 +1460,7 @@ fn updateTlv(
1473 sym_index: Symbol.Index,1460 sym_index: Symbol.Index,
1474 shndx: u32,1461 shndx: u32,
1475 code: []const u8,1462 code: []const u8,
1476) link.File.UpdateNavError!void {1463) link.Error!void {
1477 const zcu = pt.zcu;1464 const zcu = pt.zcu;
1478 const ip = &zcu.intern_pool;1465 const ip = &zcu.intern_pool;
1479 const gpa = zcu.gpa;1466 const gpa = zcu.gpa;
...@@ -1531,7 +1518,7 @@ pub fn updateFunc(...@@ -1531,7 +1518,7 @@ pub fn updateFunc(
1531 pt: Zcu.PerThread,1518 pt: Zcu.PerThread,
1532 func_index: InternPool.Index,1519 func_index: InternPool.Index,
1533 mir: *const codegen.AnyMir,1520 mir: *const codegen.AnyMir,
1534) link.File.UpdateNavError!void {1521) link.Error!void {
1535 const tracy = trace(@src());1522 const tracy = trace(@src());
1536 defer tracy.end();1523 defer tracy.end();
15371524
...@@ -1558,7 +1545,6 @@ pub fn updateFunc(...@@ -1558,7 +1545,6 @@ pub fn updateFunc(
1558 codegen.emitFunction(1545 codegen.emitFunction(
1559 &elf_file.base,1546 &elf_file.base,
1560 pt,1547 pt,
1561 zcu.navSrcLoc(func.owner_nav),
1562 func_index,1548 func_index,
1563 @enumFromInt(sym_index),1549 @enumFromInt(sym_index),
1564 mir,1550 mir,
...@@ -1645,7 +1631,7 @@ pub fn updateNav(...@@ -1645,7 +1631,7 @@ pub fn updateNav(
1645 elf_file: *Elf,1631 elf_file: *Elf,
1646 pt: Zcu.PerThread,1632 pt: Zcu.PerThread,
1647 nav_index: InternPool.Nav.Index,1633 nav_index: InternPool.Nav.Index,
1648) link.File.UpdateNavError!void {1634) link.Error!void {
1649 const tracy = trace(@src());1635 const tracy = trace(@src());
1650 defer tracy.end();1636 defer tracy.end();
16511637
...@@ -1670,7 +1656,7 @@ pub fn updateNav(...@@ -1670,7 +1656,7 @@ pub fn updateNav(
1670 var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, @enumFromInt(sym_index));1656 var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, @enumFromInt(sym_index));
1671 defer debug_wip_nav.deinit();1657 defer debug_wip_nav.deinit();
1672 dwarf.finishWipNav(pt, nav_index, &debug_wip_nav) catch |err| switch (err) {1658 dwarf.finishWipNav(pt, nav_index, &debug_wip_nav) catch |err| switch (err) {
1673 error.OutOfMemory, error.Overflow => |e| return e,1659 error.OutOfMemory, error.Canceled, error.AlreadyReported => |e| return e,
1674 else => |e| return elf_file.base.cgFail(nav_index, "failed to finish dwarf nav: {s}", .{@errorName(e)}),1660 else => |e| return elf_file.base.cgFail(nav_index, "failed to finish dwarf nav: {s}", .{@errorName(e)}),
1675 };1661 };
1676 }1662 }
...@@ -1691,7 +1677,6 @@ pub fn updateNav(...@@ -1691,7 +1677,6 @@ pub fn updateNav(
1691 codegen.generateSymbol(1677 codegen.generateSymbol(
1692 &elf_file.base,1678 &elf_file.base,
1693 pt,1679 pt,
1694 zcu.navSrcLoc(nav_index),
1695 .fromInterned(nav.resolved.?.value),1680 .fromInterned(nav.resolved.?.value),
1696 &aw.writer,1681 &aw.writer,
1697 .{ .atom_index = @enumFromInt(sym_index) },1682 .{ .atom_index = @enumFromInt(sym_index) },
...@@ -1713,7 +1698,7 @@ pub fn updateNav(...@@ -1713,7 +1698,7 @@ pub fn updateNav(
1713 try self.updateNavCode(elf_file, pt, nav_index, sym_index, shndx, code, elf.STT_OBJECT);1698 try self.updateNavCode(elf_file, pt, nav_index, sym_index, shndx, code, elf.STT_OBJECT);
17141699
1715 if (debug_wip_nav) |*wip_nav| self.dwarf.?.finishWipNav(pt, nav_index, wip_nav) catch |err| switch (err) {1700 if (debug_wip_nav) |*wip_nav| self.dwarf.?.finishWipNav(pt, nav_index, wip_nav) catch |err| switch (err) {
1716 error.OutOfMemory, error.Overflow => |e| return e,1701 error.OutOfMemory, error.Canceled, error.AlreadyReported => |e| return e,
1717 else => |e| return elf_file.base.cgFail(nav_index, "failed to finish dwarf nav: {s}", .{@errorName(e)}),1702 else => |e| return elf_file.base.cgFail(nav_index, "failed to finish dwarf nav: {s}", .{@errorName(e)}),
1718 };1703 };
1719 } else if (self.dwarf) |*dwarf| try dwarf.updateComptimeNav(pt, nav_index);1704 } else if (self.dwarf) |*dwarf| try dwarf.updateComptimeNav(pt, nav_index);
...@@ -1759,7 +1744,6 @@ fn updateLazySymbol(...@@ -1759,7 +1744,6 @@ fn updateLazySymbol(
1759 codegen.generateLazySymbol(1744 codegen.generateLazySymbol(
1760 &elf_file.base,1745 &elf_file.base,
1761 pt,1746 pt,
1762 Type.fromInterned(sym.ty).srcLocOrNull(zcu) orelse .unneeded,
1763 sym,1747 sym,
1764 &required_alignment,1748 &required_alignment,
1765 &aw.writer,1749 &aw.writer,
...@@ -1827,8 +1811,7 @@ fn lowerConst(...@@ -1827,8 +1811,7 @@ fn lowerConst(
1827 val: Value,1811 val: Value,
1828 required_alignment: InternPool.Alignment,1812 required_alignment: InternPool.Alignment,
1829 output_section_index: u32,1813 output_section_index: u32,
1830 src_loc: Zcu.LazySrcLoc,1814) !link.File.SymbolId {
1831) !codegen.SymbolResult {
1832 const gpa = pt.zcu.gpa;1815 const gpa = pt.zcu.gpa;
18331816
1834 var aw: std.Io.Writer.Allocating = .init(gpa);1817 var aw: std.Io.Writer.Allocating = .init(gpa);
...@@ -1840,7 +1823,6 @@ fn lowerConst(...@@ -1840,7 +1823,6 @@ fn lowerConst(
1840 codegen.generateSymbol(1823 codegen.generateSymbol(
1841 &elf_file.base,1824 &elf_file.base,
1842 pt,1825 pt,
1843 src_loc,
1844 val,1826 val,
1845 &aw.writer,1827 &aw.writer,
1846 .{ .atom_index = @enumFromInt(sym_index) },1828 .{ .atom_index = @enumFromInt(sym_index) },
...@@ -1865,7 +1847,7 @@ fn lowerConst(...@@ -1865,7 +1847,7 @@ fn lowerConst(
18651847
1866 try elf_file.pwriteAll(code, atom_ptr.offset(elf_file));1848 try elf_file.pwriteAll(code, atom_ptr.offset(elf_file));
18671849
1868 return .{ .sym_index = @enumFromInt(sym_index) };1850 return @enumFromInt(sym_index);
1869}1851}
18701852
1871pub fn updateExports(1853pub fn updateExports(
...@@ -1874,7 +1856,7 @@ pub fn updateExports(...@@ -1874,7 +1856,7 @@ pub fn updateExports(
1874 pt: Zcu.PerThread,1856 pt: Zcu.PerThread,
1875 exported: Zcu.Exported,1857 exported: Zcu.Exported,
1876 export_indices: []const Zcu.Export.Index,1858 export_indices: []const Zcu.Export.Index,
1877) link.File.UpdateExportsError!void {1859) link.Error!void {
1878 const tracy = trace(@src());1860 const tracy = trace(@src());
1879 defer tracy.end();1861 defer tracy.end();
18801862
...@@ -1886,18 +1868,7 @@ pub fn updateExports(...@@ -1886,18 +1868,7 @@ pub fn updateExports(
1886 break :blk self.navs.getPtr(nav).?;1868 break :blk self.navs.getPtr(nav).?;
1887 },1869 },
1888 .uav => |uav| self.uavs.getPtr(uav) orelse blk: {1870 .uav => |uav| self.uavs.getPtr(uav) orelse blk: {
1889 const first_exp = export_indices[0].ptr(zcu);1871 _ = try self.lowerUav(elf_file, pt, uav, .none);
1890 const res = try self.lowerUav(elf_file, pt, uav, .none, first_exp.src);
1891 switch (res) {
1892 .sym_index => {},
1893 .fail => |em| {
1894 // TODO maybe it's enough to return an error here and let Zcu.processExportsInner
1895 // handle the error?
1896 try zcu.failed_exports.ensureUnusedCapacity(zcu.gpa, 1);
1897 zcu.failed_exports.putAssumeCapacityNoClobber(export_indices[0], em);
1898 return;
1899 },
1900 }
1901 break :blk self.uavs.getPtr(uav).?;1872 break :blk self.uavs.getPtr(uav).?;
1902 },1873 },
1903 };1874 };
...@@ -1962,12 +1933,12 @@ pub fn updateExports(...@@ -1962,12 +1933,12 @@ pub fn updateExports(
1962 }1933 }
1963}1934}
19641935
1965pub fn updateLineNumber(self: *ZigObject, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {1936pub fn updateLineNumber(self: *ZigObject, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) link.Error!void {
1966 if (self.dwarf) |*dwarf| {1937 if (self.dwarf) |*dwarf| {
1967 const comp = dwarf.bin_file.comp;1938 const comp = dwarf.bin_file.comp;
1968 const diags = &comp.link_diags;1939 const diags = &comp.link_diags;
1969 dwarf.updateLineNumber(pt.zcu, ti_id) catch |err| switch (err) {1940 dwarf.updateLineNumber(pt.zcu, ti_id) catch |err| switch (err) {
1970 error.Overflow, error.OutOfMemory => |e| return e,1941 error.OutOfMemory, error.Canceled, error.AlreadyReported => |e| return e,
1971 else => |e| return diags.fail("failed to update dwarf line numbers: {s}", .{@errorName(e)}),1942 else => |e| return diags.fail("failed to update dwarf line numbers: {s}", .{@errorName(e)}),
1972 };1943 };
1973 }1944 }
src/link/Elf/relocatable.zig+4-4
...@@ -23,7 +23,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {...@@ -23,7 +23,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {
23 const io = comp.io;23 const io = comp.io;
24 const diags = &comp.link_diags;24 const diags = &comp.link_diags;
2525
26 if (diags.hasErrors()) return error.LinkFailure;26 if (diags.hasErrors()) return error.AlreadyReported;
2727
28 // First, we flush relocatable object file generated with our backends.28 // First, we flush relocatable object file generated with our backends.
29 if (elf_file.zigObjectPtr()) |zig_object| {29 if (elf_file.zigObjectPtr()) |zig_object| {
...@@ -151,13 +151,13 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {...@@ -151,13 +151,13 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {
151 try elf_file.base.file.?.setLength(io, total_size);151 try elf_file.base.file.?.setLength(io, total_size);
152 try elf_file.base.file.?.writePositionalAll(io, writer.buffered(), 0);152 try elf_file.base.file.?.writePositionalAll(io, writer.buffered(), 0);
153153
154 if (diags.hasErrors()) return error.LinkFailure;154 if (diags.hasErrors()) return error.AlreadyReported;
155}155}
156156
157pub fn flushObject(elf_file: *Elf, comp: *Compilation) !void {157pub fn flushObject(elf_file: *Elf, comp: *Compilation) !void {
158 const diags = &comp.link_diags;158 const diags = &comp.link_diags;
159159
160 if (diags.hasErrors()) return error.LinkFailure;160 if (diags.hasErrors()) return error.AlreadyReported;
161161
162 // Now, we are ready to resolve the symbols across all input files.162 // Now, we are ready to resolve the symbols across all input files.
163 // We will first resolve the files in the ZigObject, next in the parsed163 // We will first resolve the files in the ZigObject, next in the parsed
...@@ -203,7 +203,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation) !void {...@@ -203,7 +203,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation) !void {
203 try elf_file.writeShdrTable();203 try elf_file.writeShdrTable();
204 try elf_file.writeElfHeader();204 try elf_file.writeElfHeader();
205205
206 if (diags.hasErrors()) return error.LinkFailure;206 if (diags.hasErrors()) return error.AlreadyReported;
207}207}
208208
209fn claimUnresolved(elf_file: *Elf) void {209fn claimUnresolved(elf_file: *Elf) void {
src/link/Elf2.zig+295-212
...@@ -162,6 +162,8 @@ const_prog_node: std.Progress.Node,...@@ -162,6 +162,8 @@ const_prog_node: std.Progress.Node,
162synth_prog_node: std.Progress.Node,162synth_prog_node: std.Progress.Node,
163input_prog_node: std.Progress.Node,163input_prog_node: std.Progress.Node,
164164
165const Error = link.Error || error{MappedFileIo};
166
165const Node = union(enum) {167const Node = union(enum) {
166 file,168 file,
167 ehdr,169 ehdr,
...@@ -478,7 +480,7 @@ const Section = struct {...@@ -478,7 +480,7 @@ const Section = struct {
478 };480 };
479 }481 }
480482
481 fn rename(shndx: Index, elf: *Elf, new_name: []const u8) !void {483 fn rename(shndx: Index, elf: *Elf, new_name: []const u8) Error!void {
482 const shstrtab_entry = try elf.string(.shstrtab, new_name);484 const shstrtab_entry = try elf.string(.shstrtab, new_name);
483 switch (elf.shdrPtr(shndx)) {485 switch (elf.shdrPtr(shndx)) {
484 inline else => |shdr| elf.targetStore(&shdr.name, @intFromEnum(shstrtab_entry)),486 inline else => |shdr| elf.targetStore(&shdr.name, @intFromEnum(shstrtab_entry)),
...@@ -487,7 +489,7 @@ const Section = struct {...@@ -487,7 +489,7 @@ const Section = struct {
487489
488 /// Asserts that `shndx` is a `SHT_RELA` section and ensures that its node has enough unused490 /// Asserts that `shndx` is a `SHT_RELA` section and ensures that its node has enough unused
489 /// space to hold `n` additional `ElfN.Rela` entries.491 /// space to hold `n` additional `ElfN.Rela` entries.
490 fn relaEnsureAdditionalCapacity(rela_shndx: Index, elf: *Elf, n: usize) !void {492 fn relaEnsureAdditionalCapacity(rela_shndx: Index, elf: *Elf, n: usize) Error!void {
491 const node = rela_shndx.get(elf).ni;493 const node = rela_shndx.get(elf).ni;
492 const need_size: u64 = switch (elf.shdrPtr(rela_shndx)) {494 const need_size: u64 = switch (elf.shdrPtr(rela_shndx)) {
493 inline else => |shdr, class| need_size: {495 inline else => |shdr, class| need_size: {
...@@ -509,11 +511,7 @@ const Section = struct {...@@ -509,11 +511,7 @@ const Section = struct {
509 break :need_size cur_size + need_additional * ent_size;511 break :need_size cur_size + need_additional * ent_size;
510 },512 },
511 };513 };
512 _, const cur_node_size = node.location(&elf.mf).resolve(&elf.mf);514 try elf.ensureNodeSize(node, need_size);
513 if (need_size > cur_node_size) {
514 const gpa = elf.base.comp.gpa;
515 try node.resize(&elf.mf, gpa, need_size +| need_size / MappedFile.growth_factor);
516 }
517 }515 }
518516
519 /// Asserts that `shndx` is a `SHT_RELA` section and deletes the `ElfN.Rela` entry at the517 /// Asserts that `shndx` is a `SHT_RELA` section and deletes the `ElfN.Rela` entry at the
...@@ -1192,7 +1190,7 @@ const SymbolReloc = struct {...@@ -1192,7 +1190,7 @@ const SymbolReloc = struct {
1192 }1190 }
1193};1191};
11941192
1195fn ensureUnusedSymbolCapacity(elf: *Elf, len: u32, kind: enum { all_local, maybe_global }) !void {1193fn ensureUnusedSymbolCapacity(elf: *Elf, len: u32, kind: enum { all_local, maybe_global }) Error!void {
1196 const gpa = elf.base.comp.gpa;1194 const gpa = elf.base.comp.gpa;
11971195
1198 try elf.symtab.ensureUnusedCapacity(gpa, len);1196 try elf.symtab.ensureUnusedCapacity(gpa, len);
...@@ -1210,11 +1208,7 @@ fn ensureUnusedSymbolCapacity(elf: *Elf, len: u32, kind: enum { all_local, maybe...@@ -1210,11 +1208,7 @@ fn ensureUnusedSymbolCapacity(elf: *Elf, len: u32, kind: enum { all_local, maybe
1210 const need_node_size: u64 = switch (elf.shdrPtr(.symtab)) {1208 const need_node_size: u64 = switch (elf.shdrPtr(.symtab)) {
1211 inline else => |shdr, class| elf.targetLoad(&shdr.size) + len * @sizeOf(class.ElfN().Sym),1209 inline else => |shdr, class| elf.targetLoad(&shdr.size) + len * @sizeOf(class.ElfN().Sym),
1212 };1210 };
1213 _, const cur_node_size = Section.Index.symtab.get(elf).ni.location(&elf.mf).resolve(&elf.mf);1211 try elf.ensureNodeSize(Section.Index.symtab.get(elf).ni, need_node_size);
1214 if (cur_node_size < need_node_size) {
1215 const new_node_size = need_node_size +| need_node_size / MappedFile.growth_factor;
1216 try Section.Index.symtab.get(elf).ni.resize(&elf.mf, gpa, new_node_size);
1217 }
1218 }1212 }
12191213
1220 switch (kind) {1214 switch (kind) {
...@@ -1232,18 +1226,14 @@ fn ensureUnusedSymbolCapacity(elf: *Elf, len: u32, kind: enum { all_local, maybe...@@ -1232,18 +1226,14 @@ fn ensureUnusedSymbolCapacity(elf: *Elf, len: u32, kind: enum { all_local, maybe
1232 const dynsym_need_size: u64 = switch (elf.shdrPtr(elf.shndx.dynsym)) {1226 const dynsym_need_size: u64 = switch (elf.shdrPtr(elf.shndx.dynsym)) {
1233 inline else => |shdr, class| elf.targetLoad(&shdr.size) + len * @sizeOf(class.ElfN().Sym),1227 inline else => |shdr, class| elf.targetLoad(&shdr.size) + len * @sizeOf(class.ElfN().Sym),
1234 };1228 };
1235 _, const dynsym_cur_size = elf.shndx.dynsym.get(elf).ni.location(&elf.mf).resolve(&elf.mf);1229 try elf.ensureNodeSize(elf.shndx.dynsym.get(elf).ni, dynsym_need_size);
1236 if (dynsym_cur_size < dynsym_need_size) {
1237 const new_size = dynsym_need_size +| dynsym_need_size / MappedFile.growth_factor;
1238 try elf.shndx.dynsym.get(elf).ni.resize(&elf.mf, gpa, new_size);
1239 }
12401230
1241 try elf.ensureUnusedPltCapacity(len);1231 try elf.ensureUnusedPltCapacity(len);
1242 }1232 }
1243 },1233 },
1244 }1234 }
1245}1235}
1246fn ensureUnusedPltCapacity(elf: *Elf, len: u32) !void {1236fn ensureUnusedPltCapacity(elf: *Elf, len: u32) Error!void {
1247 const gpa = elf.base.comp.gpa;1237 const gpa = elf.base.comp.gpa;
12481238
1249 try elf.shndx.rela_plt.relaEnsureAdditionalCapacity(elf, len);1239 try elf.shndx.rela_plt.relaEnsureAdditionalCapacity(elf, len);
...@@ -1256,30 +1246,18 @@ fn ensureUnusedPltCapacity(elf: *Elf, len: u32) !void {...@@ -1256,30 +1246,18 @@ fn ensureUnusedPltCapacity(elf: *Elf, len: u32) !void {
1256 .X86_64 => {1246 .X86_64 => {
1257 // Ensure the `.plt` section's node is big enough1247 // Ensure the `.plt` section's node is big enough
1258 const plt_need_size: usize = 16 * (1 + need_plt_capacity);1248 const plt_need_size: usize = 16 * (1 + need_plt_capacity);
1259 _, const plt_cur_size = elf.shndx.plt.get(elf).ni.location(&elf.mf).resolve(&elf.mf);1249 try elf.ensureNodeSize(elf.shndx.plt.get(elf).ni, plt_need_size);
1260 if (plt_cur_size < plt_need_size) {
1261 const new_size = plt_need_size +| plt_need_size / MappedFile.growth_factor;
1262 try elf.shndx.plt.get(elf).ni.resize(&elf.mf, gpa, new_size);
1263 }
12641250
1265 // Ensure the `.got.plt` section's node is big enough1251 // Ensure the `.got.plt` section's node is big enough
1266 const got_plt_need_size: usize = switch (elf.identClass()) {1252 const got_plt_need_size: usize = switch (elf.identClass()) {
1267 .NONE, _ => unreachable,1253 .NONE, _ => unreachable,
1268 inline else => |class| @sizeOf(class.ElfN().Addr) * (3 + need_plt_capacity),1254 inline else => |class| @sizeOf(class.ElfN().Addr) * (3 + need_plt_capacity),
1269 };1255 };
1270 _, const got_plt_cur_size = elf.shndx.got_plt.get(elf).ni.location(&elf.mf).resolve(&elf.mf);1256 try elf.ensureNodeSize(elf.shndx.got_plt.get(elf).ni, got_plt_need_size);
1271 if (got_plt_cur_size < got_plt_need_size) {
1272 const new_size = got_plt_need_size +| got_plt_need_size / MappedFile.growth_factor;
1273 try elf.shndx.got_plt.get(elf).ni.resize(&elf.mf, gpa, new_size);
1274 }
12751257
1276 // Ensure the `.plt.sec` section's node is big enough1258 // Ensure the `.plt.sec` section's node is big enough
1277 const plt_sec_need_size: usize = 16 * need_plt_capacity;1259 const plt_sec_need_size: usize = 16 * need_plt_capacity;
1278 _, const plt_sec_cur_size = elf.shndx.plt_sec.get(elf).ni.location(&elf.mf).resolve(&elf.mf);1260 try elf.ensureNodeSize(elf.shndx.plt_sec.get(elf).ni, plt_sec_need_size);
1279 if (plt_sec_cur_size < plt_sec_need_size) {
1280 const new_size = plt_sec_need_size +| plt_sec_need_size / MappedFile.growth_factor;
1281 try elf.shndx.plt_sec.get(elf).ni.resize(&elf.mf, gpa, new_size);
1282 }
1283 },1261 },
1284 }1262 }
1285}1263}
...@@ -1375,7 +1353,7 @@ const AddGlobalSymbolOptions = struct {...@@ -1375,7 +1353,7 @@ const AddGlobalSymbolOptions = struct {
1375 const Name = struct {1353 const Name = struct {
1376 strtab: String(.strtab),1354 strtab: String(.strtab),
1377 dynstr: String(.dynstr),1355 dynstr: String(.dynstr),
1378 fn string(elf: *Elf, slice: []const u8) !Name {1356 fn string(elf: *Elf, slice: []const u8) Error!Name {
1379 return .{1357 return .{
1380 .strtab = try elf.string(.strtab, slice),1358 .strtab = try elf.string(.strtab, slice),
1381 .dynstr = switch (elf.shndx.dynsym) {1359 .dynstr = switch (elf.shndx.dynsym) {
...@@ -2205,7 +2183,14 @@ pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId {...@@ -2205,7 +2183,14 @@ pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId {
2205 const s: Symbol.Id = .local(lsi);2183 const s: Symbol.Id = .local(lsi);
2206 return s.toTypeErased();2184 return s.toTypeErased();
2207}2185}
2208pub fn lazySymbol(elf: *Elf, lazy: link.File.LazySymbol) !link.File.SymbolId {2186pub fn lazySymbol(elf: *Elf, lazy: link.File.LazySymbol) link.Error!link.File.SymbolId {
2187 const diags = &elf.base.comp.link_diags;
2188 return elf.lazySymbolInner(lazy) catch |err| switch (err) {
2189 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
2190 else => |e| return e,
2191 };
2192}
2193fn lazySymbolInner(elf: *Elf, lazy: link.File.LazySymbol) Error!link.File.SymbolId {
2209 const gpa = elf.base.comp.gpa;2194 const gpa = elf.base.comp.gpa;
22102195
2211 try elf.ensureUnusedSymbolCapacity(1, .all_local);2196 try elf.ensureUnusedSymbolCapacity(1, .all_local);
...@@ -2246,13 +2231,21 @@ pub fn lazySymbol(elf: *Elf, lazy: link.File.LazySymbol) !link.File.SymbolId {...@@ -2246,13 +2231,21 @@ pub fn lazySymbol(elf: *Elf, lazy: link.File.LazySymbol) !link.File.SymbolId {
2246 const s: Symbol.Id = .local(gop.value_ptr.lsi);2231 const s: Symbol.Id = .local(gop.value_ptr.lsi);
2247 return s.toTypeErased();2232 return s.toTypeErased();
2248}2233}
2249pub fn externSymbol(elf: *Elf, opts: struct {2234pub const ExternSymbolOpts = struct {
2250 name: []const u8,2235 name: []const u8,
2251 lib_name: ?[]const u8,2236 lib_name: ?[]const u8,
2252 type: std.elf.STT,2237 type: std.elf.STT,
2253 linkage: std.lang.GlobalLinkage = .strong,2238 linkage: std.lang.GlobalLinkage = .strong,
2254 visibility: std.lang.SymbolVisibility = .default,2239 visibility: std.lang.SymbolVisibility = .default,
2255}) !link.File.SymbolId {2240};
2241pub fn externSymbol(elf: *Elf, opts: ExternSymbolOpts) link.Error!link.File.SymbolId {
2242 const diags = &elf.base.comp.link_diags;
2243 return elf.externSymbolInner(opts) catch |err| switch (err) {
2244 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
2245 else => |e| return e,
2246 };
2247}
2248fn externSymbolInner(elf: *Elf, opts: ExternSymbolOpts) Error!link.File.SymbolId {
2256 try elf.ensureUnusedSymbolCapacity(1, .maybe_global);2249 try elf.ensureUnusedSymbolCapacity(1, .maybe_global);
2257 const symbol = elf.addGlobalSymbolAssumeCapacity(.{2250 const symbol = elf.addGlobalSymbolAssumeCapacity(.{
2258 .node = .none,2251 .node = .none,
...@@ -2265,7 +2258,7 @@ pub fn externSymbol(elf: *Elf, opts: struct {...@@ -2265,7 +2258,7 @@ pub fn externSymbol(elf: *Elf, opts: struct {
2265 .internal => @panic("TODO internal extern symbol"),2258 .internal => @panic("TODO internal extern symbol"),
2266 .strong => .strong,2259 .strong => .strong,
2267 .weak => .weak,2260 .weak => .weak,
2268 .link_once => return error.LinkOnceUnsupported,2261 .link_once => return elf.base.comp.link_diags.fail("TODO(Elf2): link_once is not supported", .{}),
2269 },2262 },
2270 .visibility = switch (opts.visibility) {2263 .visibility = switch (opts.visibility) {
2271 .default => .DEFAULT,2264 .default => .DEFAULT,
...@@ -2285,12 +2278,20 @@ pub fn addReloc(...@@ -2285,12 +2278,20 @@ pub fn addReloc(
2285 target: link.File.SymbolId,2278 target: link.File.SymbolId,
2286 addend: i64,2279 addend: i64,
2287 @"type": MachineRelocType,2280 @"type": MachineRelocType,
2288) !void {2281) link.Error!void {
2289 const node: MappedFile.Node.Index = Node.fromAtom(atom);2282 const node: MappedFile.Node.Index = Node.fromAtom(atom);
2290 try elf.ensureUnusedRelocCapacity(node, 1);2283 const diags = &elf.base.comp.link_diags;
2291 try elf.addRelocAssumeCapacity(node, offset, .fromTypeErased(target), addend, @"type");2284 elf.ensureUnusedRelocCapacity(node, 1) catch |err| switch (err) {
2285 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
2286 else => |e| return e,
2287 };
2288 elf.addRelocAssumeCapacity(node, offset, .fromTypeErased(target), addend, @"type") catch |err| switch (err) {
2289 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
2290 else => |e| return e,
2291 };
2292}2292}
2293pub fn navSymbol(elf: *Elf, nav_index: InternPool.Nav.Index) !link.File.SymbolId {2293pub fn navSymbol(elf: *Elf, nav_index: InternPool.Nav.Index) link.Error!link.File.SymbolId {
2294 const diags = &elf.base.comp.link_diags;
2294 const zcu = elf.base.comp.zcu.?;2295 const zcu = elf.base.comp.zcu.?;
2295 const ip = &zcu.intern_pool;2296 const ip = &zcu.intern_pool;
2296 const nav = ip.getNav(nav_index);2297 const nav = ip.getNav(nav_index);
...@@ -2303,7 +2304,10 @@ pub fn navSymbol(elf: *Elf, nav_index: InternPool.Nav.Index) !link.File.SymbolId...@@ -2303,7 +2304,10 @@ pub fn navSymbol(elf: *Elf, nav_index: InternPool.Nav.Index) !link.File.SymbolId
2303 .visibility = @"extern".visibility,2304 .visibility = @"extern".visibility,
2304 });2305 });
2305 }2306 }
2306 const nmi = try elf.navMapIndex(zcu, nav_index);2307 const nmi = elf.navMapIndex(zcu, nav_index) catch |err| switch (err) {
2308 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
2309 else => |e| return e,
2310 };
2307 const s: Symbol.Id = .local(nmi.symbol(elf));2311 const s: Symbol.Id = .local(nmi.symbol(elf));
2308 return s.toTypeErased();2312 return s.toTypeErased();
2309}2313}
...@@ -2311,8 +2315,12 @@ pub fn uavSymbol(...@@ -2311,8 +2315,12 @@ pub fn uavSymbol(
2311 elf: *Elf,2315 elf: *Elf,
2312 uav_val: InternPool.Index,2316 uav_val: InternPool.Index,
2313 uav_align: InternPool.Alignment,2317 uav_align: InternPool.Alignment,
2314) !link.File.SymbolId {2318) link.Error!link.File.SymbolId {
2315 const umi = try elf.uavMapIndex(uav_val, uav_align);2319 const diags = &elf.base.comp.link_diags;
2320 const umi = elf.uavMapIndex(uav_val, uav_align) catch |err| switch (err) {
2321 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
2322 else => |e| return e,
2323 };
2316 const s: Symbol.Id = .local(umi.symbol(elf));2324 const s: Symbol.Id = .local(umi.symbol(elf));
2317 return s.toTypeErased();2325 return s.toTypeErased();
2318}2326}
...@@ -2321,7 +2329,7 @@ pub fn getNavVAddr(...@@ -2321,7 +2329,7 @@ pub fn getNavVAddr(
2321 pt: Zcu.PerThread,2329 pt: Zcu.PerThread,
2322 nav: InternPool.Nav.Index,2330 nav: InternPool.Nav.Index,
2323 reloc_info: link.File.RelocInfo,2331 reloc_info: link.File.RelocInfo,
2324) !u64 {2332) link.Error!u64 {
2325 _ = pt;2333 _ = pt;
2326 return elf.getVAddr(reloc_info, try elf.navSymbol(nav));2334 return elf.getVAddr(reloc_info, try elf.navSymbol(nav));
2327}2335}
...@@ -2329,41 +2337,33 @@ pub fn getUavVAddr(...@@ -2329,41 +2337,33 @@ pub fn getUavVAddr(
2329 elf: *Elf,2337 elf: *Elf,
2330 uav_val: InternPool.Index,2338 uav_val: InternPool.Index,
2331 reloc_info: link.File.RelocInfo,2339 reloc_info: link.File.RelocInfo,
2332) !u64 {2340) link.Error!u64 {
2333 return elf.getVAddr(reloc_info, try elf.uavSymbol(uav_val, .none));2341 return elf.getVAddr(reloc_info, try elf.uavSymbol(uav_val, .none));
2334}2342}
2335pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target: link.File.SymbolId) !u64 {2343pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target: link.File.SymbolId) link.Error!u64 {
2336 const node: MappedFile.Node.Index = Node.fromAtom(reloc_info.parent.atom_index);2344 try elf.addReloc(
2337 const target_sym: Symbol.Id = .fromTypeErased(target);2345 reloc_info.parent.atom_index,
2338 try elf.ensureUnusedRelocCapacity(node, 1);
2339 try elf.addRelocAssumeCapacity(
2340 node,
2341 reloc_info.offset,2346 reloc_info.offset,
2342 target_sym,2347 target,
2343 reloc_info.addend,2348 reloc_info.addend,
2344 .absAddr(elf),2349 .absAddr(elf),
2345 );2350 );
2346 return target_sym.value(elf);2351 return Symbol.Id.fromTypeErased(target).value(elf);
2347}2352}
2348pub fn lowerUav(2353pub fn lowerUav(
2349 elf: *Elf,2354 elf: *Elf,
2350 pt: Zcu.PerThread,2355 pt: Zcu.PerThread,
2351 uav_val: InternPool.Index,2356 uav_val: InternPool.Index,
2352 uav_align: InternPool.Alignment,2357 uav_align: InternPool.Alignment,
2353 src_loc: Zcu.LazySrcLoc,2358) link.Error!link.File.SymbolId {
2354) !codegen.SymbolResult {
2355 _ = pt;2359 _ = pt;
2360 const diags = &elf.base.comp.link_diags;
2356 const umi = elf.uavMapIndex(uav_val, uav_align) catch |err| switch (err) {2361 const umi = elf.uavMapIndex(uav_val, uav_align) catch |err| switch (err) {
2357 error.OutOfMemory => |e| return e,2362 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
2358 else => |e| return .{ .fail = try Zcu.ErrorMsg.create(2363 else => |e| return e,
2359 elf.base.comp.gpa,
2360 src_loc,
2361 "linker failed to update constant: {s}",
2362 .{@errorName(e)},
2363 ) },
2364 };2364 };
2365 const s: Symbol.Id = .local(umi.symbol(elf));2365 const s: Symbol.Id = .local(umi.symbol(elf));
2366 return .{ .sym_index = s.toTypeErased() };2366 return s.toTypeErased();
2367}2367}
23682368
2369const StringSection = enum {2369const StringSection = enum {
...@@ -2390,7 +2390,7 @@ fn String(section: StringSection) type {...@@ -2390,7 +2390,7 @@ fn String(section: StringSection) type {
2390 }2390 }
2391 };2391 };
2392}2392}
2393fn string(elf: *Elf, comptime section: StringSection, key: []const u8) !String(section) {2393fn string(elf: *Elf, comptime section: StringSection, key: []const u8) Error!String(section) {
2394 const st: *StringTable = &@field(elf, @tagName(section));2394 const st: *StringTable = &@field(elf, @tagName(section));
2395 return @enumFromInt(try st.get(elf, section.shndx(elf), key));2395 return @enumFromInt(try st.get(elf, section.shndx(elf), key));
2396}2396}
...@@ -2424,7 +2424,7 @@ const StringTable = struct {...@@ -2424,7 +2424,7 @@ const StringTable = struct {
2424 }2424 }
2425 };2425 };
24262426
2427 pub fn get(st: *StringTable, elf: *Elf, shndx: Section.Index, key: []const u8) !u32 {2427 pub fn get(st: *StringTable, elf: *Elf, shndx: Section.Index, key: []const u8) Error!u32 {
2428 // If we are in `initHeaders` the strtab might not be initalized yet, so we need to special2428 // If we are in `initHeaders` the strtab might not be initalized yet, so we need to special
2429 // case the empty string.2429 // case the empty string.
2430 if (key.len == 0) return 0;2430 if (key.len == 0) return 0;
...@@ -2450,9 +2450,7 @@ const StringTable = struct {...@@ -2450,9 +2450,7 @@ const StringTable = struct {
2450 if (shndx == elf.shndx.dynstr) {2450 if (shndx == elf.shndx.dynstr) {
2451 elf.updateDynamicEntry(std.elf.DT_STRSZ, new_size);2451 elf.updateDynamicEntry(std.elf.DT_STRSZ, new_size);
2452 }2452 }
2453 _, const node_size = ni.location(&elf.mf).resolve(&elf.mf);2453 try elf.ensureNodeSize(ni, new_size);
2454 if (new_size > node_size)
2455 try ni.resize(&elf.mf, gpa, new_size +| new_size / MappedFile.growth_factor);
2456 const slice = ni.slice(&elf.mf)[old_size..];2454 const slice = ni.slice(&elf.mf)[old_size..];
2457 @memcpy(slice[0..key.len], key);2455 @memcpy(slice[0..key.len], key);
2458 slice[key.len] = 0;2456 slice[key.len] = 0;
...@@ -3615,7 +3613,13 @@ fn mapInputSection(elf: *Elf, opts: struct {...@@ -3615,7 +3613,13 @@ fn mapInputSection(elf: *Elf, opts: struct {
3615 flags: std.elf.SHF,3613 flags: std.elf.SHF,
3616 addralign: std.elf.Xword,3614 addralign: std.elf.Xword,
3617 entsize: std.elf.Xword,3615 entsize: std.elf.Xword,
3618}) !Section.Index {3616}) (Error || error{
3617 UnsupportedSectionFlags,
3618 TlsSectionUnavailable,
3619 StripSection,
3620 SectionFlagsConflict,
3621 SectionTypeConflict,
3622})!Section.Index {
3619 const gpa = elf.base.comp.gpa;3623 const gpa = elf.base.comp.gpa;
3620 if (opts.flags.INFO_LINK or3624 if (opts.flags.INFO_LINK or
3621 opts.flags.LINK_ORDER or3625 opts.flags.LINK_ORDER or
...@@ -3733,7 +3737,7 @@ fn mapInputSection(elf: *Elf, opts: struct {...@@ -3733,7 +3737,7 @@ fn mapInputSection(elf: *Elf, opts: struct {
3733 }3737 }
3734 return existing_shndx;3738 return existing_shndx;
3735}3739}
3736fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.NavMapIndex {3740fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node.NavMapIndex {
3737 const gpa = zcu.gpa;3741 const gpa = zcu.gpa;
3738 const ip = &zcu.intern_pool;3742 const ip = &zcu.intern_pool;
3739 const nav = ip.getNav(nav_index);3743 const nav = ip.getNav(nav_index);
...@@ -3826,7 +3830,7 @@ fn uavMapIndex(...@@ -3826,7 +3830,7 @@ fn uavMapIndex(
3826 elf: *Elf,3830 elf: *Elf,
3827 uav_val: InternPool.Index,3831 uav_val: InternPool.Index,
3828 uav_align: InternPool.Alignment,3832 uav_align: InternPool.Alignment,
3829) !Node.UavMapIndex {3833) Error!Node.UavMapIndex {
3830 const gpa = elf.base.comp.gpa;3834 const gpa = elf.base.comp.gpa;
3831 const zcu = elf.base.comp.zcu.?;3835 const zcu = elf.base.comp.zcu.?;
38323836
...@@ -3878,26 +3882,78 @@ fn uavMapIndex(...@@ -3878,26 +3882,78 @@ fn uavMapIndex(
3878 return umi;3882 return umi;
3879}3883}
38803884
3881pub fn loadInput(elf: *Elf, input: link.Input) (Io.File.Reader.SizeError ||3885/// Internal error set used by input parsing functions `loadObject`, `loadArchive`, `loadDso`.
3882 Io.File.Reader.Error || MappedFile.Error || error{ EndOfStream, BadMagic, LinkFailure })!void {3886const LoadParseInputError = Error || Io.File.SeekError || Io.Reader.Error;
3883 const io = elf.base.comp.io;3887
3888/// Returns `error.BadMagic` if a DSO or static archive has an incorrect magic number, which
3889/// indicates to the frontend that the input could be a GNU ld script instead.
3890pub fn loadInput(elf: *Elf, input: link.Input) (link.Error || error{BadMagic})!void {
3891 const diags = &elf.base.comp.link_diags;
3892 return elf.loadInputInner(input) catch |err| switch (err) {
3893 else => |e| return e,
3894 error.MappedFileIo => return diags.fail(
3895 "failed to write output file: {t}",
3896 .{elf.mf.io_err.?},
3897 ),
3898 };
3899}
3900fn loadInputInner(elf: *Elf, input: link.Input) (Error || error{BadMagic})!void {
3901 const comp = elf.base.comp;
3902 const diags = &comp.link_diags;
3903 const io = comp.io;
3884 var buf: [4096]u8 = undefined;3904 var buf: [4096]u8 = undefined;
3885 switch (input) {3905 switch (input) {
3886 .object => |object| {3906 .object => |object| {
3887 var fr = object.file.reader(io, &buf);3907 var fr = object.file.reader(io, &buf);
3888 elf.loadObject(object.path, null, &fr, .{3908 elf.loadObject(object.path, null, &fr, .{
3889 .offset = fr.logicalPos(),3909 .offset = fr.logicalPos(),
3890 .size = try fr.getSize(),3910 .size = fr.getSize() catch |err| switch (err) {
3911 error.Canceled => |e| return e,
3912 else => |e| return diags.fail(
3913 "failed to stat \"{f}\": {t}",
3914 .{ object.path.fmtEscapeString(), e },
3915 ),
3916 },
3891 }) catch |err| switch (err) {3917 }) catch |err| switch (err) {
3892 error.ReadFailed => return fr.err.?,
3893 else => |e| return e,3918 else => |e| return e,
3919 error.EndOfStream => return diags.failParse(
3920 object.path,
3921 "unexpected eof",
3922 .{},
3923 ),
3924 error.AccessDenied, error.Unexpected, error.Unseekable => |e| return diags.fail(
3925 "failed to read \"{f}\": {t}",
3926 .{ object.path.fmtEscapeString(), e },
3927 ),
3928 error.ReadFailed => switch (fr.err.?) {
3929 error.Canceled => |e| return e,
3930 else => |e| return diags.fail(
3931 "failed to read \"{f}\": {t}",
3932 .{ object.path.fmtEscapeString(), e },
3933 ),
3934 },
3894 };3935 };
3895 },3936 },
3896 .archive => |archive| {3937 .archive => |archive| {
3897 var fr = archive.file.reader(io, &buf);3938 var fr = archive.file.reader(io, &buf);
3898 elf.loadArchive(archive.path, &fr) catch |err| switch (err) {3939 elf.loadArchive(archive.path, &fr) catch |err| switch (err) {
3899 error.ReadFailed => return fr.err.?,
3900 else => |e| return e,3940 else => |e| return e,
3941 error.EndOfStream => return diags.failParse(
3942 archive.path,
3943 "unexpected eof",
3944 .{},
3945 ),
3946 error.AccessDenied, error.Unexpected, error.Unseekable => |e| return diags.fail(
3947 "failed to read \"{f}\": {t}",
3948 .{ archive.path.fmtEscapeString(), e },
3949 ),
3950 error.ReadFailed => switch (fr.err.?) {
3951 error.Canceled => |e| return e,
3952 else => |e| return diags.fail(
3953 "failed to read \"{f}\": {t}",
3954 .{ archive.path.fmtEscapeString(), e },
3955 ),
3956 },
3901 };3957 };
3902 },3958 },
3903 .res => unreachable,3959 .res => unreachable,
...@@ -3905,8 +3961,23 @@ pub fn loadInput(elf: *Elf, input: link.Input) (Io.File.Reader.SizeError ||...@@ -3905,8 +3961,23 @@ pub fn loadInput(elf: *Elf, input: link.Input) (Io.File.Reader.SizeError ||
3905 try elf.needed.ensureUnusedCapacity(elf.base.comp.gpa, 1);3961 try elf.needed.ensureUnusedCapacity(elf.base.comp.gpa, 1);
3906 var fr = dso.file.reader(io, &buf);3962 var fr = dso.file.reader(io, &buf);
3907 elf.loadDso(dso.path, &fr) catch |err| switch (err) {3963 elf.loadDso(dso.path, &fr) catch |err| switch (err) {
3908 error.ReadFailed => return fr.err.?,
3909 else => |e| return e,3964 else => |e| return e,
3965 error.EndOfStream => return diags.failParse(
3966 dso.path,
3967 "unexpected eof",
3968 .{},
3969 ),
3970 error.AccessDenied, error.Unexpected, error.Unseekable => |e| return diags.fail(
3971 "failed to read \"{f}\": {t}",
3972 .{ dso.path.fmtEscapeString(), e },
3973 ),
3974 error.ReadFailed => switch (fr.err.?) {
3975 error.Canceled => |e| return e,
3976 else => |e| return diags.fail(
3977 "failed to read \"{f}\": {t}",
3978 .{ dso.path.fmtEscapeString(), e },
3979 ),
3980 },
3910 };3981 };
3911 },3982 },
3912 .dso_exact => |dso_exact| {3983 .dso_exact => |dso_exact| {
...@@ -3919,14 +3990,22 @@ pub fn loadInput(elf: *Elf, input: link.Input) (Io.File.Reader.SizeError ||...@@ -3919,14 +3990,22 @@ pub fn loadInput(elf: *Elf, input: link.Input) (Io.File.Reader.SizeError ||
3919 },3990 },
3920 }3991 }
3921}3992}
3922fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) !void {3993fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (LoadParseInputError || error{BadMagic})!void {
3923 const comp = elf.base.comp;3994 const comp = elf.base.comp;
3924 const gpa = comp.gpa;3995 const gpa = comp.gpa;
3925 const diags = &comp.link_diags;3996 const diags = &comp.link_diags;
3926 const r = &fr.interface;3997 const r = &fr.interface;
39273998
3928 log.debug("loadArchive({f})", .{path.fmtEscapeString()});3999 log.debug("loadArchive({f})", .{path.fmtEscapeString()});
3929 if (!std.mem.eql(u8, try r.take(std.elf.ARMAG.len), std.elf.ARMAG)) return error.BadMagic;4000 {
4001 const magic = r.take(std.elf.ARMAG.len) catch |err| switch (err) {
4002 error.ReadFailed => |e| return e,
4003 error.EndOfStream => return error.BadMagic,
4004 };
4005 if (!std.mem.eql(u8, magic, std.elf.ARMAG)) {
4006 return error.BadMagic;
4007 }
4008 }
3930 var strtab: std.Io.Writer.Allocating = .init(gpa);4009 var strtab: std.Io.Writer.Allocating = .init(gpa);
3931 defer strtab.deinit();4010 defer strtab.deinit();
3932 while (r.takeStruct(std.elf.ar_hdr, native_endian)) |header| {4011 while (r.takeStruct(std.elf.ar_hdr, native_endian)) |header| {
...@@ -3987,7 +4066,7 @@ fn loadObject(...@@ -3987,7 +4066,7 @@ fn loadObject(
3987 member: ?[]const u8,4066 member: ?[]const u8,
3988 fr: *Io.File.Reader,4067 fr: *Io.File.Reader,
3989 fl: MappedFile.Node.FileLocation,4068 fl: MappedFile.Node.FileLocation,
3990) !void {4069) LoadParseInputError!void {
3991 const comp = elf.base.comp;4070 const comp = elf.base.comp;
3992 const gpa = comp.gpa;4071 const gpa = comp.gpa;
3993 const diags = &comp.link_diags;4072 const diags = &comp.link_diags;
...@@ -3995,7 +4074,14 @@ fn loadObject(...@@ -3995,7 +4074,14 @@ fn loadObject(
39954074
3996 const input_index: Node.InputIndex = @enumFromInt(elf.inputs.items.len);4075 const input_index: Node.InputIndex = @enumFromInt(elf.inputs.items.len);
3997 log.debug("loadObject({f}{f})", .{ path.fmtEscapeString(), fmtMemberString(member) });4076 log.debug("loadObject({f}{f})", .{ path.fmtEscapeString(), fmtMemberString(member) });
3998 try elf.checkInputIdent(path, r);4077 elf.checkInputIdent(path, r) catch |err| switch (err) {
4078 else => |e| return e,
4079 error.BadMagic => return diags.failParse(
4080 path,
4081 "bad ELF magic",
4082 .{},
4083 ),
4084 };
3999 try elf.ensureUnusedSymbolCapacity(1, .all_local);4085 try elf.ensureUnusedSymbolCapacity(1, .all_local);
4000 try elf.inputs.ensureUnusedCapacity(gpa, 1);4086 try elf.inputs.ensureUnusedCapacity(gpa, 1);
4001 const file_symbol = elf.addLocalSymbolAssumeCapacity(.{4087 const file_symbol = elf.addLocalSymbolAssumeCapacity(.{
...@@ -4376,7 +4462,7 @@ fn loadObject(...@@ -4376,7 +4462,7 @@ fn loadObject(
4376 },4462 },
4377 }4463 }
4378}4464}
4379fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) !void {4465fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (LoadParseInputError || error{BadMagic})!void {
4380 const comp = elf.base.comp;4466 const comp = elf.base.comp;
4381 const gpa = comp.gpa;4467 const gpa = comp.gpa;
4382 const diags = &comp.link_diags;4468 const diags = &comp.link_diags;
...@@ -4593,23 +4679,29 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) !void {...@@ -4593,23 +4679,29 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) !void {
45934679
4594/// Validates that the `std.elf.Ident` present at the start of `r` is a compatible link input.4680/// Validates that the `std.elf.Ident` present at the start of `r` is a compatible link input.
4595///4681///
4596/// Returns an error if it is incompatible, or if the ident is broken or missing.4682/// Returns an error if it is incompatible, or if the ident is broken or missing---usually
4683/// `error.AlreadyReported`, but if the magic number is missing or incorrect, returns
4684/// `error.BadMagic` instead.
4597///4685///
4598/// Does not advance the position of `r`. Requires `r` to have a 16-byte buffer.4686/// Does not advance the position of `r`. Requires `r` to have a 16-byte buffer.
4599fn checkInputIdent(4687fn checkInputIdent(
4600 elf: *const Elf,4688 elf: *const Elf,
4601 path: std.Build.Cache.Path,4689 path: std.Build.Cache.Path,
4602 r: *Io.Reader,4690 r: *Io.Reader,
4603) !void {4691) error{ BadMagic, EndOfStream, AlreadyReported, ReadFailed }!void {
4604 const diags = &elf.base.comp.link_diags;4692 const diags = &elf.base.comp.link_diags;
46054693
4606 const ident = try r.peekStructPointer(std.elf.Ident);4694 const magic = r.peek(std.elf.MAGIC.len) catch |err| switch (err) {
4607 const target: *const std.elf.Ident = @ptrCast(elf.mf.memory_map.memory[0..@sizeOf(std.elf.Ident)]);4695 error.ReadFailed => |e| return e,
46084696 error.EndOfStream => return error.BadMagic,
4609 if (!std.mem.eql(u8, &ident.magic, std.elf.MAGIC)) {4697 };
4698 if (!std.mem.eql(u8, magic, std.elf.MAGIC)) {
4610 return error.BadMagic;4699 return error.BadMagic;
4611 }4700 }
46124701
4702 const ident = try r.peekStructPointer(std.elf.Ident);
4703 const target: *const std.elf.Ident = @ptrCast(elf.mf.memory_map.memory[0..@sizeOf(std.elf.Ident)]);
4704
4613 if (ident.class != target.class) return diags.failParse(4705 if (ident.class != target.class) return diags.failParse(
4614 path,4706 path,
4615 "bad ELF class ({?s})",4707 "bad ELF class ({?s})",
...@@ -4649,7 +4741,7 @@ fn createInitFiniArraySection(...@@ -4649,7 +4741,7 @@ fn createInitFiniArraySection(
4649 shndx: *Section.Index,4741 shndx: *Section.Index,
4650 comptime name: []const u8,4742 comptime name: []const u8,
4651 @"type": std.elf.SHT,4743 @"type": std.elf.SHT,
4652) !void {4744) Error!void {
4653 assert(shndx.* == .UNDEF);4745 assert(shndx.* == .UNDEF);
4654 const gpa = elf.base.comp.gpa;4746 const gpa = elf.base.comp.gpa;
4655 const addr_align: std.mem.Alignment = switch (elf.identClass()) {4747 const addr_align: std.mem.Alignment = switch (elf.identClass()) {
...@@ -4722,14 +4814,15 @@ fn updateInitFiniArraySectionSize(...@@ -4722,14 +4814,15 @@ fn updateInitFiniArraySectionSize(
4722 Symbol.Id.global(end_sym_name).flushMoved(elf, end_vaddr);4814 Symbol.Id.global(end_sym_name).flushMoved(elf, end_vaddr);
4723}4815}
47244816
4725pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) !void {4817pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) link.Error!void {
4726 _ = prog_node;4818 _ = prog_node;
4819 const diags = &elf.base.comp.link_diags;
4727 elf.prelinkInner() catch |err| switch (err) {4820 elf.prelinkInner() catch |err| switch (err) {
4728 error.OutOfMemory => |e| return e,4821 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
4729 else => |e| return elf.base.comp.link_diags.fail("prelink failed: {t}", .{e}),4822 else => |e| return e,
4730 };4823 };
4731}4824}
4732fn prelinkInner(elf: *Elf) !void {4825fn prelinkInner(elf: *Elf) Error!void {
4733 const comp = elf.base.comp;4826 const comp = elf.base.comp;
4734 const gpa = comp.gpa;4827 const gpa = comp.gpa;
4735 try elf.ensureUnusedSymbolCapacity(1, .all_local);4828 try elf.ensureUnusedSymbolCapacity(1, .all_local);
...@@ -4954,7 +5047,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {...@@ -4954,7 +5047,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
4954 entsize: std.elf.Word = 0,5047 entsize: std.elf.Word = 0,
4955 node_align: std.mem.Alignment = .@"1",5048 node_align: std.mem.Alignment = .@"1",
4956 fixed: bool = false,5049 fixed: bool = false,
4957}) !Section.Index {5050}) Error!Section.Index {
4958 switch (opts.type) {5051 switch (opts.type) {
4959 .NULL => assert(opts.size == 0),5052 .NULL => assert(opts.size == 0),
4960 .PROGBITS => assert(opts.size > 0),5053 .PROGBITS => assert(opts.size > 0),
...@@ -4996,9 +5089,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {...@@ -4996,9 +5089,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
4996 break :shndx .{ @enumFromInt(shndx), @as(u64, elf.targetLoad(&ehdr.shentsize)) * @as(u64, shnum) };5089 break :shndx .{ @enumFromInt(shndx), @as(u64, elf.targetLoad(&ehdr.shentsize)) * @as(u64, shnum) };
4997 },5090 },
4998 };5091 };
4999 _, const shdr_node_size = elf.ni.shdr.location(&elf.mf).resolve(&elf.mf);5092 try elf.ensureNodeSize(elf.ni.shdr, new_shdr_size);
5000 if (new_shdr_size > shdr_node_size)
5001 try elf.ni.shdr.resize(&elf.mf, gpa, new_shdr_size +| new_shdr_size / MappedFile.growth_factor);
5002 const ni = try elf.mf.addLastChildNode(gpa, switch (elf.ehdrField(.type)) {5093 const ni = try elf.mf.addLastChildNode(gpa, switch (elf.ehdrField(.type)) {
5003 .NONE, .CORE, _ => unreachable,5094 .NONE, .CORE, _ => unreachable,
5004 .REL => elf.ni.file,5095 .REL => elf.ni.file,
...@@ -5045,7 +5136,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {...@@ -5045,7 +5136,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
5045 return shndx;5136 return shndx;
5046}5137}
50475138
5048fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize) !void {5139fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize) Error!void {
5049 if (len == 0) return;5140 if (len == 0) return;
5050 const gpa = elf.base.comp.gpa;5141 const gpa = elf.base.comp.gpa;
5051 try elf.symbol_relocs.ensureUnusedCapacity(gpa, len);5142 try elf.symbol_relocs.ensureUnusedCapacity(gpa, len);
...@@ -5090,14 +5181,11 @@ fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize)...@@ -5090,14 +5181,11 @@ fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize)
5090 try elf.tls_size_symbol_relocs.ensureUnusedCapacity(gpa, len);5181 try elf.tls_size_symbol_relocs.ensureUnusedCapacity(gpa, len);
5091 const new_got_entries = len * 2; // at worst, every reloc is a new TLSGD5182 const new_got_entries = len * 2; // at worst, every reloc is a new TLSGD
5092 try elf.got.ensureUnusedCapacity(gpa, new_got_entries);5183 try elf.got.ensureUnusedCapacity(gpa, new_got_entries);
5093 const got_ni = elf.shndx.got.get(elf).ni;
5094 _, const got_node_size = got_ni.location(&elf.mf).resolve(&elf.mf);
5095 const need_got_size = switch (class) {5184 const need_got_size = switch (class) {
5096 .NONE, _ => unreachable,5185 .NONE, _ => unreachable,
5097 inline else => |ct_class| (elf.got.count() + new_got_entries) * @sizeOf(ct_class.ElfN().Addr),5186 inline else => |ct_class| (elf.got.count() + new_got_entries) * @sizeOf(ct_class.ElfN().Addr),
5098 };5187 };
5099 if (need_got_size > got_node_size)5188 try elf.ensureNodeSize(elf.shndx.got.get(elf).ni, need_got_size);
5100 try got_ni.resize(&elf.mf, gpa, need_got_size +| need_got_size / MappedFile.growth_factor);
51015189
5102 if (elf.shndx.dynamic != .UNDEF) {5190 if (elf.shndx.dynamic != .UNDEF) {
5103 try elf.shndx.rela_dyn.relaEnsureAdditionalCapacity(elf, new_got_entries);5191 try elf.shndx.rela_dyn.relaEnsureAdditionalCapacity(elf, new_got_entries);
...@@ -5114,7 +5202,7 @@ fn addRelocAssumeCapacity(...@@ -5114,7 +5202,7 @@ fn addRelocAssumeCapacity(
5114 target: Symbol.Id,5202 target: Symbol.Id,
5115 addend: i64,5203 addend: i64,
5116 @"type": MachineRelocType,5204 @"type": MachineRelocType,
5117) !void {5205) Error!void {
5118 assert(node != .none);5206 assert(node != .none);
5119 switch (elf.ehdrField(.type)) {5207 switch (elf.ehdrField(.type)) {
5120 .NONE, .CORE, _ => unreachable,5208 .NONE, .CORE, _ => unreachable,
...@@ -5233,7 +5321,7 @@ fn addSymbolRelocAssumeCapacity(...@@ -5233,7 +5321,7 @@ fn addSymbolRelocAssumeCapacity(
5233 target: Symbol.Id,5321 target: Symbol.Id,
5234 addend: i64,5322 addend: i64,
5235 @"type": SymbolReloc.Type,5323 @"type": SymbolReloc.Type,
5236) !void {5324) Error!void {
5237 assert(elf.ehdrField(.type) != .REL);5325 assert(elf.ehdrField(.type) != .REL);
52385326
5239 const rela_index: Section.RelaIndex.Optional = r: {5327 const rela_index: Section.RelaIndex.Optional = r: {
...@@ -5594,7 +5682,7 @@ fn nodeWantsDsoRelocation(elf: *Elf, node: MappedFile.Node.Index) enum { yes, ye...@@ -5594,7 +5682,7 @@ fn nodeWantsDsoRelocation(elf: *Elf, node: MappedFile.Node.Index) enum { yes, ye
5594/// global where needed---the caller does not need to do this.5682/// global where needed---the caller does not need to do this.
5595///5683///
5596/// Asserts that `elf.shndx.dynamic != .UNDEF` and that `global_name` refers to an *undefined* global.5684/// Asserts that `elf.shndx.dynamic != .UNDEF` and that `global_name` refers to an *undefined* global.
5597fn maybeAddCopyRelocation(elf: *Elf, global_name: String(.strtab)) !bool {5685fn maybeAddCopyRelocation(elf: *Elf, global_name: String(.strtab)) Error!bool {
5598 assert(elf.shndx.dynamic != .UNDEF);5686 assert(elf.shndx.dynamic != .UNDEF);
55995687
5600 const gpa = elf.base.comp.gpa;5688 const gpa = elf.base.comp.gpa;
...@@ -5657,16 +5745,14 @@ fn maybeAddCopyRelocation(elf: *Elf, global_name: String(.strtab)) !bool {...@@ -5657,16 +5745,14 @@ fn maybeAddCopyRelocation(elf: *Elf, global_name: String(.strtab)) !bool {
5657 return true;5745 return true;
5658}5746}
56595747
5660pub fn updateNav(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {5748pub fn updateNav(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) link.Error!void {
5749 const diags = &elf.base.comp.link_diags;
5661 elf.updateNavInner(pt, nav_index) catch |err| switch (err) {5750 elf.updateNavInner(pt, nav_index) catch |err| switch (err) {
5662 error.OutOfMemory,5751 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
5663 error.Overflow,5752 else => |e| return e,
5664 error.RelocationNotByteAligned,
5665 => |e| return e,
5666 else => |e| return elf.base.cgFail(nav_index, "linker failed to update variable: {t}", .{e}),
5667 };5753 };
5668}5754}
5669fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {5755fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) Error!void {
5670 const zcu = pt.zcu;5756 const zcu = pt.zcu;
5671 const gpa = zcu.gpa;5757 const gpa = zcu.gpa;
5672 const ip = &zcu.intern_pool;5758 const ip = &zcu.intern_pool;
...@@ -5689,12 +5775,11 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)...@@ -5689,12 +5775,11 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)
5689 codegen.generateSymbol(5775 codegen.generateSymbol(
5690 &elf.base,5776 &elf.base,
5691 pt,5777 pt,
5692 zcu.navSrcLoc(nav_index),
5693 .fromInterned(nav.resolved.?.value),5778 .fromInterned(nav.resolved.?.value),
5694 &nw.interface,5779 &nw.interface,
5695 .{ .atom_index = Node.toAtom(ni) },5780 .{ .atom_index = Node.toAtom(ni) },
5696 ) catch |err| switch (err) {5781 ) catch |err| switch (err) {
5697 error.WriteFailed => return error.OutOfMemory,5782 error.WriteFailed => return nw.err.?,
5698 else => |e| return e,5783 else => |e| return e,
5699 };5784 };
5700 switch (elf.symPtr(nmi.symbol(elf).index())) {5785 switch (elf.symPtr(nmi.symbol(elf).index())) {
...@@ -5707,18 +5792,11 @@ pub fn updateFunc(...@@ -5707,18 +5792,11 @@ pub fn updateFunc(
5707 pt: Zcu.PerThread,5792 pt: Zcu.PerThread,
5708 func_index: InternPool.Index,5793 func_index: InternPool.Index,
5709 mir: *const codegen.AnyMir,5794 mir: *const codegen.AnyMir,
5710) !void {5795) link.Error!void {
5796 const diags = &elf.base.comp.link_diags;
5711 elf.updateFuncInner(pt, func_index, mir) catch |err| switch (err) {5797 elf.updateFuncInner(pt, func_index, mir) catch |err| switch (err) {
5712 error.OutOfMemory,5798 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
5713 error.Overflow,5799 else => |e| return e,
5714 error.RelocationNotByteAligned,
5715 error.CodegenFail,
5716 => |e| return e,
5717 else => |e| return elf.base.cgFail(
5718 pt.zcu.funcInfo(func_index).owner_nav,
5719 "linker failed to update function: {s}",
5720 .{@errorName(e)},
5721 ),
5722 };5800 };
5723}5801}
5724fn updateFuncInner(5802fn updateFuncInner(
...@@ -5726,7 +5804,7 @@ fn updateFuncInner(...@@ -5726,7 +5804,7 @@ fn updateFuncInner(
5726 pt: Zcu.PerThread,5804 pt: Zcu.PerThread,
5727 func_index: InternPool.Index,5805 func_index: InternPool.Index,
5728 mir: *const codegen.AnyMir,5806 mir: *const codegen.AnyMir,
5729) !void {5807) Error!void {
5730 const zcu = pt.zcu;5808 const zcu = pt.zcu;
5731 const gpa = zcu.gpa;5809 const gpa = zcu.gpa;
5732 const ip = &zcu.intern_pool;5810 const ip = &zcu.intern_pool;
...@@ -5748,7 +5826,6 @@ fn updateFuncInner(...@@ -5748,7 +5826,6 @@ fn updateFuncInner(
5748 codegen.emitFunction(5826 codegen.emitFunction(
5749 &elf.base,5827 &elf.base,
5750 pt,5828 pt,
5751 zcu.navSrcLoc(func.owner_nav),
5752 func_index,5829 func_index,
5753 Node.toAtom(ni),5830 Node.toAtom(ni),
5754 mir,5831 mir,
...@@ -5763,14 +5840,14 @@ fn updateFuncInner(...@@ -5763,14 +5840,14 @@ fn updateFuncInner(
5763 }5840 }
5764}5841}
57655842
5766pub fn updateErrorData(elf: *Elf, pt: Zcu.PerThread) !void {5843pub fn updateErrorData(elf: *Elf, pt: Zcu.PerThread) link.Error!void {
5844 const diags = &elf.base.comp.link_diags;
5767 elf.flushLazy(pt, .{5845 elf.flushLazy(pt, .{
5768 .kind = .const_data,5846 .kind = .const_data,
5769 .index = @intCast(elf.lazy.getPtr(.const_data).map.getIndex(.anyerror_type) orelse return),5847 .index = @intCast(elf.lazy.getPtr(.const_data).map.getIndex(.anyerror_type) orelse return),
5770 }) catch |err| switch (err) {5848 }) catch |err| switch (err) {
5771 error.OutOfMemory => |e| return e,5849 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
5772 error.CodegenFail => return error.LinkFailure,5850 else => |e| return e,
5773 else => |e| return elf.base.comp.link_diags.fail("updateErrorData failed: {t}", .{e}),
5774 };5851 };
5775}5852}
57765853
...@@ -5779,8 +5856,9 @@ pub fn flush(...@@ -5779,8 +5856,9 @@ pub fn flush(
5779 arena: std.mem.Allocator,5856 arena: std.mem.Allocator,
5780 tid: Zcu.PerThread.Id,5857 tid: Zcu.PerThread.Id,
5781 prog_node: std.Progress.Node,5858 prog_node: std.Progress.Node,
5782) !void {5859) link.Error!void {
5783 const comp = elf.base.comp;5860 const comp = elf.base.comp;
5861 const diags = &comp.link_diags;
5784 _ = arena;5862 _ = arena;
5785 _ = prog_node;5863 _ = prog_node;
57865864
...@@ -5791,12 +5869,12 @@ pub fn flush(...@@ -5791,12 +5869,12 @@ pub fn flush(
5791 any_undef = true;5869 any_undef = true;
5792 comp.link_diags.addError("undefined global symbol '{s}'", .{name.slice(elf)});5870 comp.link_diags.addError("undefined global symbol '{s}'", .{name.slice(elf)});
5793 }5871 }
5794 if (any_undef) return error.LinkFailure;5872 if (any_undef) return error.AlreadyReported;
5795 }5873 }
57965874
5797 elf.updateDynamicTextrel() catch |err| switch (err) {5875 elf.updateDynamicTextrel() catch |err| switch (err) {
5798 error.OutOfMemory => |e| return e,5876 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
5799 else => |e| return elf.base.comp.link_diags.fail("updateDynamicTextrel failed: {t}", .{e}),5877 else => |e| return e,
5800 };5878 };
58015879
5802 while (try elf.idle(tid)) {}5880 while (try elf.idle(tid)) {}
...@@ -5812,8 +5890,8 @@ pub fn flush(...@@ -5812,8 +5890,8 @@ pub fn flush(
5812 .named => |named| named,5890 .named => |named| named,
5813 };5891 };
5814 const sym_name_strtab = elf.string(.strtab, sym_name_slice) catch |err| switch (err) {5892 const sym_name_strtab = elf.string(.strtab, sym_name_slice) catch |err| switch (err) {
5815 error.Canceled => |e| return e,5893 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
5816 else => |e| return comp.link_diags.fail("flush write failed: {t}", .{e}),5894 else => |e| return e,
5817 };5895 };
5818 if (elf.globalByName(sym_name_strtab) == null) break :entry 0;5896 if (elf.globalByName(sym_name_strtab) == null) break :entry 0;
5819 break :entry Symbol.Id.global(sym_name_strtab).value(elf);5897 break :entry Symbol.Id.global(sym_name_strtab).value(elf);
...@@ -5823,11 +5901,11 @@ pub fn flush(...@@ -5823,11 +5901,11 @@ pub fn flush(
5823 }5901 }
58245902
5825 elf.mf.flush() catch |err| switch (err) {5903 elf.mf.flush() catch |err| switch (err) {
5826 error.Canceled => |e| return e,5904 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
5827 else => |e| return comp.link_diags.fail("flush write failed: {t}", .{e}),5905 else => |e| return e,
5828 };5906 };
5829}5907}
5830fn updateDynamicTextrel(elf: *Elf) !void {5908fn updateDynamicTextrel(elf: *Elf) Error!void {
5831 if (elf.shndx.dynamic == .UNDEF) return;5909 if (elf.shndx.dynamic == .UNDEF) return;
5832 const dynamic_ni = elf.shndx.dynamic.get(elf).ni;5910 const dynamic_ni = elf.shndx.dynamic.get(elf).ni;
5833 switch (elf.shdrPtr(elf.shndx.dynamic)) {5911 switch (elf.shdrPtr(elf.shndx.dynamic)) {
...@@ -5844,10 +5922,7 @@ fn updateDynamicTextrel(elf: *Elf) !void {...@@ -5844,10 +5922,7 @@ fn updateDynamicTextrel(elf: *Elf) !void {
5844 if (!has_textrel) {5922 if (!has_textrel) {
5845 // Add a DT_TEXTREL entry before the final DT_NULL entry.5923 // Add a DT_TEXTREL entry before the final DT_NULL entry.
5846 const new_size = cur_size + @sizeOf([2]class.ElfN().Addr);5924 const new_size = cur_size + @sizeOf([2]class.ElfN().Addr);
5847 _, const node_size = dynamic_ni.location(&elf.mf).resolve(&elf.mf);5925 try elf.ensureNodeSize(dynamic_ni, new_size);
5848 if (node_size < new_size) {
5849 try dynamic_ni.resize(&elf.mf, elf.base.comp.gpa, new_size);
5850 }
5851 elf.targetStore(&shdr.size, new_size);5926 elf.targetStore(&shdr.size, new_size);
5852 const new_entries: [][2]class.ElfN().Addr = @ptrCast(@alignCast(5927 const new_entries: [][2]class.ElfN().Addr = @ptrCast(@alignCast(
5853 dynamic_ni.slice(&elf.mf)[0..@intCast(new_size)],5928 dynamic_ni.slice(&elf.mf)[0..@intCast(new_size)],
...@@ -5869,18 +5944,16 @@ fn updateDynamicTextrel(elf: *Elf) !void {...@@ -5869,18 +5944,16 @@ fn updateDynamicTextrel(elf: *Elf) !void {
5869 }5944 }
5870}5945}
58715946
5872pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) !bool {5947pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {
5873 const comp = elf.base.comp;5948 const comp = elf.base.comp;
5949 const diags = &comp.link_diags;
5874 task: {5950 task: {
5875 while (elf.pending_uavs.pop()) |umi| {5951 while (elf.pending_uavs.pop()) |umi| {
5876 const sub_prog_node = elf.idleProgNode(tid, elf.const_prog_node, .{ .uav = umi });5952 const sub_prog_node = elf.idleProgNode(tid, elf.const_prog_node, .{ .uav = umi });
5877 defer sub_prog_node.end();5953 defer sub_prog_node.end();
5878 elf.flushUav(.{ .zcu = comp.zcu.?, .tid = tid }, umi) catch |err| switch (err) {5954 elf.flushUav(.{ .zcu = comp.zcu.?, .tid = tid }, umi) catch |err| switch (err) {
5879 error.OutOfMemory => |e| return e,5955 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
5880 else => |e| return comp.link_diags.fail(5956 else => |e| return e,
5881 "linker failed to lower constant: {t}",
5882 .{e},
5883 ),
5884 };5957 };
5885 break :task;5958 break :task;
5886 }5959 }
...@@ -5903,11 +5976,8 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) !bool {...@@ -5903,11 +5976,8 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) !bool {
5903 );5976 );
5904 defer sub_prog_node.end();5977 defer sub_prog_node.end();
5905 elf.flushLazy(pt, lmr) catch |err| switch (err) {5978 elf.flushLazy(pt, lmr) catch |err| switch (err) {
5906 error.OutOfMemory => |e| return e,5979 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
5907 else => |e| return comp.link_diags.fail(5980 else => |e| return e,
5908 "linker failed to lower lazy {s}: {t}",
5909 .{ kind, e },
5910 ),
5911 };5981 };
5912 break :task;5982 break :task;
5913 };5983 };
...@@ -5917,18 +5987,8 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) !bool {...@@ -5917,18 +5987,8 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) !bool {
5917 const sub_prog_node = elf.idleProgNode(tid, elf.input_prog_node, elf.getNode(isi.node(elf)));5987 const sub_prog_node = elf.idleProgNode(tid, elf.input_prog_node, elf.getNode(isi.node(elf)));
5918 defer sub_prog_node.end();5988 defer sub_prog_node.end();
5919 elf.flushInputSection(isi) catch |err| switch (err) {5989 elf.flushInputSection(isi) catch |err| switch (err) {
5920 else => |e| {5990 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
5921 const ii = isi.input(elf);5991 else => |e| return e,
5922 return comp.link_diags.fail(
5923 "linker failed to read input section '{s}' from \"{f}{f}\": {t}",
5924 .{
5925 elf.getNode(isi.node(elf).parent(&elf.mf)).section.name(elf).slice(elf),
5926 ii.path(elf).fmtEscapeString(),
5927 fmtMemberString(ii.member(elf)),
5928 e,
5929 },
5930 );
5931 },
5932 };5992 };
5933 break :task;5993 break :task;
5934 }5994 }
...@@ -6005,10 +6065,9 @@ fn flushUav(...@@ -6005,10 +6065,9 @@ fn flushUav(
6005 elf: *Elf,6065 elf: *Elf,
6006 pt: Zcu.PerThread,6066 pt: Zcu.PerThread,
6007 umi: Node.UavMapIndex,6067 umi: Node.UavMapIndex,
6008) !void {6068) Error!void {
6009 const comp = elf.base.comp;6069 const comp = elf.base.comp;
6010 const gpa = comp.gpa;6070 const gpa = comp.gpa;
6011 const zcu = pt.zcu;
60126071
6013 const uav_val = umi.uavValue(elf);6072 const uav_val = umi.uavValue(elf);
6014 const ni = umi.symbol(elf).index().ptr(elf).node;6073 const ni = umi.symbol(elf).index().ptr(elf).node;
...@@ -6017,23 +6076,14 @@ fn flushUav(...@@ -6017,23 +6076,14 @@ fn flushUav(
6017 var nw: MappedFile.Node.Writer = undefined;6076 var nw: MappedFile.Node.Writer = undefined;
6018 ni.writer(&elf.mf, gpa, &nw);6077 ni.writer(&elf.mf, gpa, &nw);
6019 defer nw.deinit();6078 defer nw.deinit();
6020 // TODO: UAV lowering should never require source locations.
6021 const dummy_src_loc: Zcu.LazySrcLoc = .{
6022 .base_node_inst = try zcu.intern_pool.trackZir(gpa, comp.io, pt.tid, .{
6023 .file = zcu.module_roots.get(zcu.std_mod).?.unwrap().?,
6024 .inst = .main_struct_inst,
6025 }),
6026 .offset = .{ .byte_abs = 0 },
6027 };
6028 codegen.generateSymbol(6079 codegen.generateSymbol(
6029 &elf.base,6080 &elf.base,
6030 pt,6081 pt,
6031 dummy_src_loc,
6032 .fromInterned(uav_val),6082 .fromInterned(uav_val),
6033 &nw.interface,6083 &nw.interface,
6034 .{ .atom_index = Node.toAtom(ni) },6084 .{ .atom_index = Node.toAtom(ni) },
6035 ) catch |err| switch (err) {6085 ) catch |err| switch (err) {
6036 error.WriteFailed => return error.OutOfMemory,6086 error.WriteFailed => return nw.err.?,
6037 else => |e| return e,6087 else => |e| return e,
6038 };6088 };
6039 switch (elf.symPtr(umi.symbol(elf).index())) {6089 switch (elf.symPtr(umi.symbol(elf).index())) {
...@@ -6044,7 +6094,7 @@ fn flushUav(...@@ -6044,7 +6094,7 @@ fn flushUav(
6044 assert(ni.hasMoved(&elf.mf));6094 assert(ni.hasMoved(&elf.mf));
6045}6095}
60466096
6047fn flushLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {6097fn flushLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) Error!void {
6048 const zcu = pt.zcu;6098 const zcu = pt.zcu;
6049 const gpa = zcu.gpa;6099 const gpa = zcu.gpa;
60506100
...@@ -6060,44 +6110,70 @@ fn flushLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {...@@ -6060,44 +6110,70 @@ fn flushLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {
6060 var nw: MappedFile.Node.Writer = undefined;6110 var nw: MappedFile.Node.Writer = undefined;
6061 ni.writer(&elf.mf, gpa, &nw);6111 ni.writer(&elf.mf, gpa, &nw);
6062 defer nw.deinit();6112 defer nw.deinit();
6063 try codegen.generateLazySymbol(6113 codegen.generateLazySymbol(
6064 &elf.base,6114 &elf.base,
6065 pt,6115 pt,
6066 Type.fromInterned(lazy.ty).srcLocOrNull(pt.zcu) orelse .unneeded,
6067 lazy,6116 lazy,
6068 &required_alignment,6117 &required_alignment,
6069 &nw.interface,6118 &nw.interface,
6070 .none,6119 .none,
6071 .{ .atom_index = Node.toAtom(ni) },6120 .{ .atom_index = Node.toAtom(ni) },
6072 );6121 ) catch |err| switch (err) {
6122 error.WriteFailed => return nw.err.?,
6123 else => |e| return e,
6124 };
6073 switch (elf.symPtr(lmr.symbol(elf).index())) {6125 switch (elf.symPtr(lmr.symbol(elf).index())) {
6074 inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)),6126 inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)),
6075 }6127 }
6076}6128}
60776129
6078fn flushInputSection(elf: *Elf, isi: InputSection.Index) !void {6130fn flushInputSection(elf: *Elf, isi: InputSection.Index) Error!void {
6079 const file_loc = isi.fileLocation(elf);6131 const file_loc = isi.fileLocation(elf);
6080 if (file_loc.size == 0) return;6132 if (file_loc.size == 0) return;
6081 const comp = elf.base.comp;6133 const comp = elf.base.comp;
6082 const io = comp.io;6134 const io = comp.io;
6083 const gpa = comp.gpa;6135 const gpa = comp.gpa;
6136 const diags = &comp.link_diags;
6084 const ii = isi.input(elf);6137 const ii = isi.input(elf);
6085 const path = ii.path(elf);6138 const path = ii.path(elf);
6086 const file = try path.root_dir.handle.openFile(io, path.sub_path, .{});6139 const file = path.root_dir.handle.openFile(io, path.sub_path, .{}) catch |err| switch (err) {
6140 error.Canceled => |e| return e,
6141 else => |e| return diags.fail("failed to open input file \"{f}\": {t}", .{ path.fmtEscapeString(), e }),
6142 };
6087 defer file.close(io);6143 defer file.close(io);
6088 var fr = file.reader(io, &.{});6144 var fr = file.reader(io, &.{});
6089 try fr.seekTo(file_loc.offset);6145 fr.seekTo(file_loc.offset) catch |err| switch (err) {
6146 error.Canceled => |e| return e,
6147 else => |e| return diags.fail("failed to read input section '{s}' from \"{f}{f}\": {t}", .{
6148 elf.getNode(isi.node(elf).parent(&elf.mf)).section.name(elf).slice(elf),
6149 path.fmtEscapeString(),
6150 fmtMemberString(ii.member(elf)),
6151 e,
6152 }),
6153 };
6090 var nw: MappedFile.Node.Writer = undefined;6154 var nw: MappedFile.Node.Writer = undefined;
6091 isi.node(elf).writer(&elf.mf, gpa, &nw);6155 isi.node(elf).writer(&elf.mf, gpa, &nw);
6092 defer nw.deinit();6156 defer nw.deinit();
6093 if (try nw.interface.sendFileAll(&fr, .limited(@intCast(file_loc.size))) != file_loc.size)6157 const n_bytes = nw.interface.sendFileAll(&fr, .limited(@intCast(file_loc.size))) catch |err| switch (err) {
6094 return error.EndOfStream;6158 error.ReadFailed => return diags.fail("failed to read input section '{s}' from \"{f}{f}\": {t}", .{
6159 elf.getNode(isi.node(elf).parent(&elf.mf)).section.name(elf).slice(elf),
6160 path.fmtEscapeString(),
6161 fmtMemberString(ii.member(elf)),
6162 fr.err orelse (fr.seek_err orelse fr.size_err.?),
6163 }),
6164 error.WriteFailed => return nw.err.?,
6165 };
6166 if (n_bytes != file_loc.size) return diags.fail("failed to read input section '{s}' from \"{f}{f}\": unexpected eof", .{
6167 elf.getNode(isi.node(elf).parent(&elf.mf)).section.name(elf).slice(elf),
6168 path.fmtEscapeString(),
6169 fmtMemberString(ii.member(elf)),
6170 });
6095 // The input section should already be considered to have moved, because it is created as moved6171 // The input section should already be considered to have moved, because it is created as moved
6096 // and pending calls to `flushInputSection` always happen before pending calls to `flushMoved`.6172 // and pending calls to `flushInputSection` always happen before pending calls to `flushMoved`.
6097 assert(isi.node(elf).hasMoved(&elf.mf));6173 assert(isi.node(elf).hasMoved(&elf.mf));
6098}6174}
60996175
6100fn flushFileOffset(elf: *Elf, ni: MappedFile.Node.Index) !void {6176fn flushFileOffset(elf: *Elf, ni: MappedFile.Node.Index) void {
6101 switch (elf.getNode(ni)) {6177 switch (elf.getNode(ni)) {
6102 else => unreachable,6178 else => unreachable,
6103 .ehdr => assert(ni.fileLocation(&elf.mf, false).offset == 0),6179 .ehdr => assert(ni.fileLocation(&elf.mf, false).offset == 0),
...@@ -6118,7 +6194,7 @@ fn flushFileOffset(elf: *Elf, ni: MappedFile.Node.Index) !void {...@@ -6118,7 +6194,7 @@ fn flushFileOffset(elf: *Elf, ni: MappedFile.Node.Index) !void {
6118 },6194 },
6119 }6195 }
6120 var child_it = ni.children(&elf.mf);6196 var child_it = ni.children(&elf.mf);
6121 while (child_it.next()) |child_ni| try elf.flushFileOffset(child_ni);6197 while (child_it.next()) |child_ni| elf.flushFileOffset(child_ni);
6122 },6198 },
6123 .section => |shndx| switch (elf.shdrPtr(shndx)) {6199 .section => |shndx| switch (elf.shdrPtr(shndx)) {
6124 inline else => |shdr| elf.targetStore(&shdr.offset, @intCast(6200 inline else => |shdr| elf.targetStore(&shdr.offset, @intCast(
...@@ -6128,14 +6204,14 @@ fn flushFileOffset(elf: *Elf, ni: MappedFile.Node.Index) !void {...@@ -6128,14 +6204,14 @@ fn flushFileOffset(elf: *Elf, ni: MappedFile.Node.Index) !void {
6128 }6204 }
6129}6205}
61306206
6131fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void {6207fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void {
6132 const trace = tracy.trace(@src());6208 const trace = tracy.trace(@src());
6133 defer trace.end();6209 defer trace.end();
6134 switch (elf.getNode(ni)) {6210 switch (elf.getNode(ni)) {
6135 .file => unreachable,6211 .file => unreachable,
6136 .ehdr, .shdr => try elf.flushFileOffset(ni),6212 .ehdr, .shdr => elf.flushFileOffset(ni),
6137 .segment => |phndx| {6213 .segment => |phndx| {
6138 try elf.flushFileOffset(ni);6214 elf.flushFileOffset(ni);
6139 switch (elf.phdrSlice()) {6215 switch (elf.phdrSlice()) {
6140 inline else => |phdr| {6216 inline else => |phdr| {
6141 const ph = &phdr[phndx];6217 const ph = &phdr[phndx];
...@@ -6156,7 +6232,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void {...@@ -6156,7 +6232,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void {
6156 }6232 }
6157 },6233 },
6158 .section => |shndx| {6234 .section => |shndx| {
6159 try elf.flushFileOffset(ni);6235 elf.flushFileOffset(ni);
6160 const addr = elf.computeNodeVAddr(ni);6236 const addr = elf.computeNodeVAddr(ni);
6161 const old_addr: u64, const flags: std.elf.SHF = switch (elf.shdrPtr(shndx)) {6237 const old_addr: u64, const flags: std.elf.SHF = switch (elf.shdrPtr(shndx)) {
6162 inline else => |shdr| .{6238 inline else => |shdr| .{
...@@ -6293,7 +6369,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void {...@@ -6293,7 +6369,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void {
6293 try ni.childrenMoved(elf.base.comp.gpa, &elf.mf);6369 try ni.childrenMoved(elf.base.comp.gpa, &elf.mf);
6294}6370}
62956371
6296fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) !void {6372fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void {
6297 const trace = tracy.trace(@src());6373 const trace = tracy.trace(@src());
6298 defer trace.end();6374 defer trace.end();
6299 _, const size = ni.location(&elf.mf).resolve(&elf.mf);6375 _, const size = ni.location(&elf.mf).resolve(&elf.mf);
...@@ -6486,16 +6562,11 @@ pub fn updateExports(...@@ -6486,16 +6562,11 @@ pub fn updateExports(
6486 pt: Zcu.PerThread,6562 pt: Zcu.PerThread,
6487 exported: Zcu.Exported,6563 exported: Zcu.Exported,
6488 export_indices: []const Zcu.Export.Index,6564 export_indices: []const Zcu.Export.Index,
6489) !void {6565) link.Error!void {
6566 const diags = &elf.base.comp.link_diags;
6490 return elf.updateExportsInner(pt, exported, export_indices) catch |err| switch (err) {6567 return elf.updateExportsInner(pt, exported, export_indices) catch |err| switch (err) {
6491 error.OutOfMemory => error.OutOfMemory,6568 else => |e| return e,
6492 error.LinkFailure => error.AnalysisFail,6569 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
6493 else => |e| switch (elf.base.comp.link_diags.fail(
6494 "linker failed to update exports: {t}",
6495 .{e},
6496 )) {
6497 error.LinkFailure => return error.AnalysisFail,
6498 },
6499 };6570 };
6500}6571}
6501fn updateExportsInner(6572fn updateExportsInner(
...@@ -6503,7 +6574,7 @@ fn updateExportsInner(...@@ -6503,7 +6574,7 @@ fn updateExportsInner(
6503 pt: Zcu.PerThread,6574 pt: Zcu.PerThread,
6504 exported: Zcu.Exported,6575 exported: Zcu.Exported,
6505 export_indices: []const Zcu.Export.Index,6576 export_indices: []const Zcu.Export.Index,
6506) !void {6577) Error!void {
6507 const zcu = pt.zcu;6578 const zcu = pt.zcu;
6508 const ip = &zcu.intern_pool;6579 const ip = &zcu.intern_pool;
65096580
...@@ -6543,7 +6614,7 @@ fn updateExportsInner(...@@ -6543,7 +6614,7 @@ fn updateExportsInner(
6543 .internal => @panic("TODO internal linkage"),6614 .internal => @panic("TODO internal linkage"),
6544 .strong => .strong,6615 .strong => .strong,
6545 .weak => .weak,6616 .weak => .weak,
6546 .link_once => return error.LinkOnceUnsupported,6617 .link_once => return elf.base.comp.link_diags.fail("TODO(Elf2): link_once is not supported", .{}),
6547 },6618 },
6548 .visibility = switch (@"export".opts.visibility) {6619 .visibility = switch (@"export".opts.visibility) {
6549 .default => .DEFAULT,6620 .default => .DEFAULT,
...@@ -6591,10 +6662,10 @@ pub fn dump(elf: *Elf, tid: Zcu.PerThread.Id) Io.Cancelable!void {...@@ -6591,10 +6662,10 @@ pub fn dump(elf: *Elf, tid: Zcu.PerThread.Id) Io.Cancelable!void {
6591pub fn printNode(6662pub fn printNode(
6592 elf: *Elf,6663 elf: *Elf,
6593 tid: Zcu.PerThread.Id,6664 tid: Zcu.PerThread.Id,
6594 w: *std.Io.Writer,6665 w: *Io.Writer,
6595 ni: MappedFile.Node.Index,6666 ni: MappedFile.Node.Index,
6596 indent: usize,6667 indent: usize,
6597) !void {6668) Io.Writer.Error!void {
6598 const node = elf.getNode(ni);6669 const node = elf.getNode(ni);
6599 try w.splatByteAll(' ', indent);6670 try w.splatByteAll(' ', indent);
6600 try w.writeAll(@tagName(node));6671 try w.writeAll(@tagName(node));
...@@ -6698,3 +6769,15 @@ pub fn printNode(...@@ -6698,3 +6769,15 @@ pub fn printNode(
6698 try w.writeByte('\n');6769 try w.writeByte('\n');
6699 }6770 }
6700}6771}
6772
6773fn ensureNodeSize(
6774 elf: *Elf,
6775 node: MappedFile.Node.Index,
6776 need_size: u64,
6777) Error!void {
6778 _, const node_size = node.location(&elf.mf).resolve(&elf.mf);
6779 if (need_size <= node_size) return;
6780 const gpa = elf.base.comp.gpa;
6781 const new_size = need_size + need_size / MappedFile.growth_factor;
6782 try node.resize(&elf.mf, gpa, new_size);
6783}
src/link/LdScript.zig+1-1
...@@ -13,7 +13,7 @@ pub fn deinit(ls: *LdScript, gpa: Allocator) void {...@@ -13,7 +13,7 @@ pub fn deinit(ls: *LdScript, gpa: Allocator) void {
13}13}
1414
15pub const Error = error{15pub const Error = error{
16 LinkFailure,16 AlreadyReported,
17 UnknownCpuArch,17 UnknownCpuArch,
18 OutOfMemory,18 OutOfMemory,
19};19};
src/link/Lld.zig+4-4
...@@ -255,7 +255,7 @@ pub fn flush(...@@ -255,7 +255,7 @@ pub fn flush(
255 arena: Allocator,255 arena: Allocator,
256 tid: Zcu.PerThread.Id,256 tid: Zcu.PerThread.Id,
257 prog_node: std.Progress.Node,257 prog_node: std.Progress.Node,
258) link.File.FlushError!void {258) link.Error!void {
259 dev.check(.lld_linker);259 dev.check(.lld_linker);
260 _ = tid;260 _ = tid;
261261
...@@ -277,7 +277,7 @@ pub fn flush(...@@ -277,7 +277,7 @@ pub fn flush(
277 .wasm => wasmLink(lld, arena),277 .wasm => wasmLink(lld, arena),
278 };278 };
279 result catch |err| switch (err) {279 result catch |err| switch (err) {
280 error.OutOfMemory, error.LinkFailure => |e| return e,280 error.OutOfMemory, error.AlreadyReported => |e| return e,
281 else => |e| return lld.base.comp.link_diags.fail("failed to link with LLD: {t}", .{e}),281 else => |e| return lld.base.comp.link_diags.fail("failed to link with LLD: {t}", .{e}),
282 };282 };
283}283}
...@@ -1620,7 +1620,7 @@ fn spawnLld(comp: *Compilation, arena: Allocator, argv: []const []const u8) !voi...@@ -1620,7 +1620,7 @@ fn spawnLld(comp: *Compilation, arena: Allocator, argv: []const []const u8) !voi
1620 const exit_code = try lldMain(arena, argv, false);1620 const exit_code = try lldMain(arena, argv, false);
1621 if (exit_code == 0) return;1621 if (exit_code == 0) return;
1622 if (comp.clang_passthrough_mode) std.process.exit(exit_code);1622 if (comp.clang_passthrough_mode) std.process.exit(exit_code);
1623 return error.LinkFailure;1623 return error.AlreadyReported;
1624 }1624 }
16251625
1626 var stderr: []u8 = &.{};1626 var stderr: []u8 = &.{};
...@@ -1720,7 +1720,7 @@ fn spawnLld(comp: *Compilation, arena: Allocator, argv: []const []const u8) !voi...@@ -1720,7 +1720,7 @@ fn spawnLld(comp: *Compilation, arena: Allocator, argv: []const []const u8) !voi
1720 .exited => |code| if (code != 0) {1720 .exited => |code| if (code != 0) {
1721 if (comp.clang_passthrough_mode) std.process.exit(code);1721 if (comp.clang_passthrough_mode) std.process.exit(code);
1722 diags.lockAndParseLldStderr(argv[1], stderr);1722 diags.lockAndParseLldStderr(argv[1], stderr);
1723 return error.LinkFailure;1723 return error.AlreadyReported;
1724 },1724 },
1725 .signal => |sig| {1725 .signal => |sig| {
1726 if (comp.clang_passthrough_mode) std.process.abort();1726 if (comp.clang_passthrough_mode) std.process.abort();
src/link/MachO.zig+32-29
...@@ -341,7 +341,7 @@ pub fn flush(...@@ -341,7 +341,7 @@ pub fn flush(
341 arena: Allocator,341 arena: Allocator,
342 tid: Zcu.PerThread.Id,342 tid: Zcu.PerThread.Id,
343 prog_node: std.Progress.Node,343 prog_node: std.Progress.Node,
344) link.File.FlushError!void {344) link.Error!void {
345 const tracy = trace(@src());345 const tracy = trace(@src());
346 defer tracy.end();346 defer tracy.end();
347347
...@@ -490,7 +490,7 @@ pub fn flush(...@@ -490,7 +490,7 @@ pub fn flush(
490 }490 }
491 };491 };
492492
493 if (diags.hasErrors()) return error.LinkFailure;493 if (diags.hasErrors()) return error.AlreadyReported;
494494
495 {495 {
496 const index = @as(File.Index, @intCast(try self.files.addOne(gpa)));496 const index = @as(File.Index, @intCast(try self.files.addOne(gpa)));
...@@ -504,7 +504,7 @@ pub fn flush(...@@ -504,7 +504,7 @@ pub fn flush(
504 try self.resolveSymbols();504 try self.resolveSymbols();
505 try self.convertTentativeDefsAndResolveSpecialSymbols();505 try self.convertTentativeDefsAndResolveSpecialSymbols();
506 self.dedupLiterals() catch |err| switch (err) {506 self.dedupLiterals() catch |err| switch (err) {
507 error.LinkFailure => |e| return e,507 error.AlreadyReported => |e| return e,
508 else => |e| return diags.fail("failed to deduplicate literals: {s}", .{@errorName(e)}),508 else => |e| return diags.fail("failed to deduplicate literals: {s}", .{@errorName(e)}),
509 };509 };
510510
...@@ -513,7 +513,7 @@ pub fn flush(...@@ -513,7 +513,7 @@ pub fn flush(
513 }513 }
514514
515 self.checkDuplicates() catch |err| switch (err) {515 self.checkDuplicates() catch |err| switch (err) {
516 error.HasDuplicates => return error.LinkFailure,516 error.HasDuplicates => return error.AlreadyReported,
517 else => |e| return diags.fail("failed to check for duplicate symbol definitions: {s}", .{@errorName(e)}),517 else => |e| return diags.fail("failed to check for duplicate symbol definitions: {s}", .{@errorName(e)}),
518 };518 };
519519
...@@ -528,7 +528,7 @@ pub fn flush(...@@ -528,7 +528,7 @@ pub fn flush(
528 self.claimUnresolved();528 self.claimUnresolved();
529529
530 self.scanRelocs() catch |err| switch (err) {530 self.scanRelocs() catch |err| switch (err) {
531 error.HasUndefinedSymbols => return error.LinkFailure,531 error.HasUndefinedSymbols => return error.AlreadyReported,
532 else => |e| return diags.fail("failed to scan relocations: {s}", .{@errorName(e)}),532 else => |e| return diags.fail("failed to scan relocations: {s}", .{@errorName(e)}),
533 };533 };
534534
...@@ -542,7 +542,7 @@ pub fn flush(...@@ -542,7 +542,7 @@ pub fn flush(
542542
543 try self.initSegments();543 try self.initSegments();
544 self.allocateSections() catch |err| switch (err) {544 self.allocateSections() catch |err| switch (err) {
545 error.LinkFailure => |e| return e,545 error.AlreadyReported => |e| return e,
546 else => |e| return diags.fail("failed to allocate sections: {s}", .{@errorName(e)}),546 else => |e| return diags.fail("failed to allocate sections: {s}", .{@errorName(e)}),
547 };547 };
548 self.allocateSegments();548 self.allocateSegments();
...@@ -558,7 +558,7 @@ pub fn flush(...@@ -558,7 +558,7 @@ pub fn flush(
558558
559 if (self.getZigObject()) |zo| {559 if (self.getZigObject()) |zo| {
560 zo.resolveRelocs(self) catch |err| switch (err) {560 zo.resolveRelocs(self) catch |err| switch (err) {
561 error.ResolveFailed => return error.LinkFailure,561 error.ResolveFailed => return error.AlreadyReported,
562 else => |e| return e,562 else => |e| return e,
563 };563 };
564 }564 }
...@@ -567,7 +567,7 @@ pub fn flush(...@@ -567,7 +567,7 @@ pub fn flush(
567 try self.writeSectionsToFile();567 try self.writeSectionsToFile();
568 try self.allocateLinkeditSegment();568 try self.allocateLinkeditSegment();
569 self.writeLinkeditSectionsToFile() catch |err| switch (err) {569 self.writeLinkeditSectionsToFile() catch |err| switch (err) {
570 error.OutOfMemory, error.LinkFailure => |e| return e,570 error.OutOfMemory, error.AlreadyReported => |e| return e,
571 else => |e| return diags.fail("failed to write linkedit sections to file: {t}", .{e}),571 else => |e| return diags.fail("failed to write linkedit sections to file: {t}", .{e}),
572 };572 };
573573
...@@ -594,11 +594,11 @@ pub fn flush(...@@ -594,11 +594,11 @@ pub fn flush(
594594
595 const ncmds, const sizeofcmds, const uuid_cmd_offset = self.writeLoadCommands() catch |err| switch (err) {595 const ncmds, const sizeofcmds, const uuid_cmd_offset = self.writeLoadCommands() catch |err| switch (err) {
596 error.WriteFailed => unreachable,596 error.WriteFailed => unreachable,
597 error.OutOfMemory, error.LinkFailure => |e| return e,597 error.OutOfMemory, error.AlreadyReported => |e| return e,
598 };598 };
599 try self.writeHeader(ncmds, sizeofcmds);599 try self.writeHeader(ncmds, sizeofcmds);
600 self.writeUuid(uuid_cmd_offset, self.requiresCodeSig()) catch |err| switch (err) {600 self.writeUuid(uuid_cmd_offset, self.requiresCodeSig()) catch |err| switch (err) {
601 error.OutOfMemory, error.LinkFailure => |e| return e,601 error.OutOfMemory, error.AlreadyReported => |e| return e,
602 else => |e| return diags.fail("failed to calculate and write uuid: {s}", .{@errorName(e)}),602 else => |e| return diags.fail("failed to calculate and write uuid: {s}", .{@errorName(e)}),
603 };603 };
604 if (self.getDebugSymbols()) |dsym| dsym.flush(self) catch |err| switch (err) {604 if (self.getDebugSymbols()) |dsym| dsym.flush(self) catch |err| switch (err) {
...@@ -609,7 +609,7 @@ pub fn flush(...@@ -609,7 +609,7 @@ pub fn flush(
609 // Code signing always comes last.609 // Code signing always comes last.
610 if (codesig) |*csig| {610 if (codesig) |*csig| {
611 self.writeCodeSignature(csig) catch |err| switch (err) {611 self.writeCodeSignature(csig) catch |err| switch (err) {
612 error.OutOfMemory, error.LinkFailure => |e| return e,612 error.OutOfMemory, error.AlreadyReported => |e| return e,
613 else => |e| return diags.fail("failed to write code signature: {s}", .{@errorName(e)}),613 else => |e| return diags.fail("failed to write code signature: {s}", .{@errorName(e)}),
614 };614 };
615 const emit = self.base.emit;615 const emit = self.base.emit;
...@@ -968,7 +968,7 @@ pub fn parseInputFiles(self: *MachO) !void {...@@ -968,7 +968,7 @@ pub fn parseInputFiles(self: *MachO) !void {
968 }968 }
969 }969 }
970970
971 if (diags.hasErrors()) return error.LinkFailure;971 if (diags.hasErrors()) return error.AlreadyReported;
972}972}
973973
974fn parseInputFileWorker(self: *MachO, file: File) void {974fn parseInputFileWorker(self: *MachO, file: File) void {
...@@ -1365,7 +1365,7 @@ fn convertTentativeDefsAndResolveSpecialSymbols(self: *MachO) !void {...@@ -1365,7 +1365,7 @@ fn convertTentativeDefsAndResolveSpecialSymbols(self: *MachO) !void {
1365 resolveSpecialSymbolsWorker(self, obj);1365 resolveSpecialSymbolsWorker(self, obj);
1366 }1366 }
1367 }1367 }
1368 if (diags.hasErrors()) return error.LinkFailure;1368 if (diags.hasErrors()) return error.AlreadyReported;
1369}1369}
13701370
1371fn convertTentativeDefinitionsWorker(self: *MachO, object: *Object) void {1371fn convertTentativeDefinitionsWorker(self: *MachO, object: *Object) void {
...@@ -1450,7 +1450,7 @@ fn checkDuplicates(self: *MachO) !void {...@@ -1450,7 +1450,7 @@ fn checkDuplicates(self: *MachO) !void {
1450 }1450 }
1451 }1451 }
14521452
1453 if (diags.hasErrors()) return error.LinkFailure;1453 if (diags.hasErrors()) return error.AlreadyReported;
14541454
1455 try self.reportDuplicates();1455 try self.reportDuplicates();
1456}1456}
...@@ -1517,7 +1517,7 @@ fn scanRelocs(self: *MachO) !void {...@@ -1517,7 +1517,7 @@ fn scanRelocs(self: *MachO) !void {
1517 }1517 }
1518 }1518 }
15191519
1520 if (diags.hasErrors()) return error.LinkFailure;1520 if (diags.hasErrors()) return error.AlreadyReported;
15211521
1522 if (self.getInternalObject()) |obj| {1522 if (self.getInternalObject()) |obj| {
1523 try obj.checkUndefs(self);1523 try obj.checkUndefs(self);
...@@ -1990,7 +1990,7 @@ fn calcSectionSizes(self: *MachO) !void {...@@ -1990,7 +1990,7 @@ fn calcSectionSizes(self: *MachO) !void {
1990 }1990 }
1991 }1991 }
19921992
1993 if (diags.hasErrors()) return error.LinkFailure;1993 if (diags.hasErrors()) return error.AlreadyReported;
19941994
1995 try self.calcSymtabSize();1995 try self.calcSymtabSize();
19961996
...@@ -2527,7 +2527,7 @@ fn writeSectionsAndUpdateLinkeditSizes(self: *MachO) !void {...@@ -2527,7 +2527,7 @@ fn writeSectionsAndUpdateLinkeditSizes(self: *MachO) !void {
2527 };2527 };
2528 }2528 }
25292529
2530 if (diags.hasErrors()) return error.LinkFailure;2530 if (diags.hasErrors()) return error.AlreadyReported;
2531}2531}
25322532
2533fn writeAtomsWorker(self: *MachO, file: File) void {2533fn writeAtomsWorker(self: *MachO, file: File) void {
...@@ -3074,15 +3074,15 @@ pub fn updateFunc(...@@ -3074,15 +3074,15 @@ pub fn updateFunc(
3074 pt: Zcu.PerThread,3074 pt: Zcu.PerThread,
3075 func_index: InternPool.Index,3075 func_index: InternPool.Index,
3076 mir: *const codegen.AnyMir,3076 mir: *const codegen.AnyMir,
3077) link.File.UpdateNavError!void {3077) link.Error!void {
3078 return self.getZigObject().?.updateFunc(self, pt, func_index, mir);3078 return self.getZigObject().?.updateFunc(self, pt, func_index, mir);
3079}3079}
30803080
3081pub fn updateNav(self: *MachO, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.File.UpdateNavError!void {3081pub fn updateNav(self: *MachO, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.Error!void {
3082 return self.getZigObject().?.updateNav(self, pt, nav);3082 return self.getZigObject().?.updateNav(self, pt, nav);
3083}3083}
30843084
3085pub fn updateLineNumber(self: *MachO, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {3085pub fn updateLineNumber(self: *MachO, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) link.Error!void {
3086 return self.getZigObject().?.updateLineNumber(pt, ti_id);3086 return self.getZigObject().?.updateLineNumber(pt, ti_id);
3087}3087}
30883088
...@@ -3091,7 +3091,7 @@ pub fn updateExports(...@@ -3091,7 +3091,7 @@ pub fn updateExports(
3091 pt: Zcu.PerThread,3091 pt: Zcu.PerThread,
3092 exported: Zcu.Exported,3092 exported: Zcu.Exported,
3093 export_indices: []const Zcu.Export.Index,3093 export_indices: []const Zcu.Export.Index,
3094) link.File.UpdateExportsError!void {3094) link.Error!void {
3095 return self.getZigObject().?.updateExports(self, pt, exported, export_indices);3095 return self.getZigObject().?.updateExports(self, pt, exported, export_indices);
3096}3096}
30973097
...@@ -3116,9 +3116,8 @@ pub fn lowerUav(...@@ -3116,9 +3116,8 @@ pub fn lowerUav(
3116 pt: Zcu.PerThread,3116 pt: Zcu.PerThread,
3117 uav: InternPool.Index,3117 uav: InternPool.Index,
3118 explicit_alignment: InternPool.Alignment,3118 explicit_alignment: InternPool.Alignment,
3119 src_loc: Zcu.LazySrcLoc,3119) !link.File.SymbolId {
3120) !codegen.SymbolResult {3120 return self.getZigObject().?.lowerUav(self, pt, uav, explicit_alignment);
3121 return self.getZigObject().?.lowerUav(self, pt, uav, explicit_alignment, src_loc);
3122}3121}
31233122
3124pub fn getUavVAddr(self: *MachO, uav: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {3123pub fn getUavVAddr(self: *MachO, uav: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {
...@@ -3265,7 +3264,11 @@ fn copyRangeAllZeroOut(self: *MachO, old_offset: u64, new_offset: u64, size: u64...@@ -3265,7 +3264,11 @@ fn copyRangeAllZeroOut(self: *MachO, old_offset: u64, new_offset: u64, size: u64
3265 file_writer.pos = new_offset;3264 file_writer.pos = new_offset;
3266 const size_u = math.cast(usize, size) orelse return error.Overflow;3265 const size_u = math.cast(usize, size) orelse return error.Overflow;
3267 const n = file_writer.interface.sendFileAll(&file_reader, .limited(size_u)) catch |err| switch (err) {3266 const n = file_writer.interface.sendFileAll(&file_reader, .limited(size_u)) catch |err| switch (err) {
3268 error.ReadFailed => return file_reader.err.?,3267 error.ReadFailed => switch (file_reader.err.?) {
3268 error.ConnectionResetByPeer => return error.Unexpected, // not a socket
3269 error.SocketUnconnected => return error.Unexpected, // not a socket
3270 else => |e| return e,
3271 },
3269 error.WriteFailed => return file_writer.err.?,3272 error.WriteFailed => return file_writer.err.?,
3270 };3273 };
3271 assert(n == size_u);3274 assert(n == size_u);
...@@ -5373,7 +5376,7 @@ fn isReachable(atom: *const Atom, rel: Relocation, macho_file: *MachO) bool {...@@ -5373,7 +5376,7 @@ fn isReachable(atom: *const Atom, rel: Relocation, macho_file: *MachO) bool {
5373 return true;5376 return true;
5374}5377}
53755378
5376pub fn pwriteAll(macho_file: *MachO, bytes: []const u8, offset: u64) error{LinkFailure}!void {5379pub fn pwriteAll(macho_file: *MachO, bytes: []const u8, offset: u64) error{AlreadyReported}!void {
5377 const comp = macho_file.base.comp;5380 const comp = macho_file.base.comp;
5378 const io = comp.io;5381 const io = comp.io;
5379 const diags = &comp.link_diags;5382 const diags = &comp.link_diags;
...@@ -5381,7 +5384,7 @@ pub fn pwriteAll(macho_file: *MachO, bytes: []const u8, offset: u64) error{LinkF...@@ -5381,7 +5384,7 @@ pub fn pwriteAll(macho_file: *MachO, bytes: []const u8, offset: u64) error{LinkF
5381 return diags.fail("failed to write: {t}", .{err});5384 return diags.fail("failed to write: {t}", .{err});
5382}5385}
53835386
5384pub fn setLength(macho_file: *MachO, length: u64) error{LinkFailure}!void {5387pub fn setLength(macho_file: *MachO, length: u64) error{AlreadyReported}!void {
5385 const comp = macho_file.base.comp;5388 const comp = macho_file.base.comp;
5386 const io = comp.io;5389 const io = comp.io;
5387 const diags = &comp.link_diags;5390 const diags = &comp.link_diags;
...@@ -5389,7 +5392,7 @@ pub fn setLength(macho_file: *MachO, length: u64) error{LinkFailure}!void {...@@ -5389,7 +5392,7 @@ pub fn setLength(macho_file: *MachO, length: u64) error{LinkFailure}!void {
5389 return diags.fail("failed to set file end pos: {t}", .{err});5392 return diags.fail("failed to set file end pos: {t}", .{err});
5390}5393}
53915394
5392pub fn cast(macho_file: *MachO, comptime T: type, x: anytype) error{LinkFailure}!T {5395pub fn cast(macho_file: *MachO, comptime T: type, x: anytype) error{AlreadyReported}!T {
5393 return std.math.cast(T, x) orelse {5396 return std.math.cast(T, x) orelse {
5394 const comp = macho_file.base.comp;5397 const comp = macho_file.base.comp;
5395 const diags = &comp.link_diags;5398 const diags = &comp.link_diags;
...@@ -5397,7 +5400,7 @@ pub fn cast(macho_file: *MachO, comptime T: type, x: anytype) error{LinkFailure}...@@ -5397,7 +5400,7 @@ pub fn cast(macho_file: *MachO, comptime T: type, x: anytype) error{LinkFailure}
5397 };5400 };
5398}5401}
53995402
5400pub fn alignPow(macho_file: *MachO, x: u32) error{LinkFailure}!u32 {5403pub fn alignPow(macho_file: *MachO, x: u32) error{AlreadyReported}!u32 {
5401 const result, const ov = @shlWithOverflow(@as(u32, 1), try cast(macho_file, u5, x));5404 const result, const ov = @shlWithOverflow(@as(u32, 1), try cast(macho_file, u5, x));
5402 if (ov != 0) {5405 if (ov != 0) {
5403 const comp = macho_file.base.comp;5406 const comp = macho_file.base.comp;
src/link/MachO/Atom.zig+1-1
...@@ -930,7 +930,7 @@ pub fn calcNumRelocs(self: Atom, macho_file: *MachO) u32 {...@@ -930,7 +930,7 @@ pub fn calcNumRelocs(self: Atom, macho_file: *MachO) u32 {
930 }930 }
931}931}
932932
933pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.relocation_info) error{ LinkFailure, OutOfMemory }!void {933pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.relocation_info) error{ AlreadyReported, OutOfMemory }!void {
934 const tracy = trace(@src());934 const tracy = trace(@src());
935 defer tracy.end();935 defer tracy.end();
936936
src/link/MachO/InternalObject.zig+1-1
...@@ -648,7 +648,7 @@ fn addSection(self: *InternalObject, allocator: Allocator, segname: []const u8,...@@ -648,7 +648,7 @@ fn addSection(self: *InternalObject, allocator: Allocator, segname: []const u8,
648 return n_sect;648 return n_sect;
649}649}
650650
651fn getSectionData(self: *const InternalObject, index: u32, macho_file: *MachO) error{LinkFailure}![]const u8 {651fn getSectionData(self: *const InternalObject, index: u32, macho_file: *MachO) error{AlreadyReported}![]const u8 {
652 const slice = self.sections.slice();652 const slice = self.sections.slice();
653 assert(index < slice.items(.header).len);653 assert(index < slice.items(.header).len);
654 const sect = slice.items(.header)[index];654 const sect = slice.items(.header)[index];
src/link/MachO/ZigObject.zig+24-48
...@@ -427,7 +427,7 @@ pub fn calcNumRelocs(self: *ZigObject, macho_file: *MachO) void {...@@ -427,7 +427,7 @@ pub fn calcNumRelocs(self: *ZigObject, macho_file: *MachO) void {
427 }427 }
428}428}
429429
430pub fn writeRelocs(self: *ZigObject, macho_file: *MachO) error{ LinkFailure, OutOfMemory }!void {430pub fn writeRelocs(self: *ZigObject, macho_file: *MachO) error{ AlreadyReported, OutOfMemory }!void {
431 const gpa = macho_file.base.comp.gpa;431 const gpa = macho_file.base.comp.gpa;
432 const diags = &macho_file.base.comp.link_diags;432 const diags = &macho_file.base.comp.link_diags;
433433
...@@ -555,7 +555,7 @@ pub fn getInputSection(self: ZigObject, atom: Atom, macho_file: *MachO) macho.se...@@ -555,7 +555,7 @@ pub fn getInputSection(self: ZigObject, atom: Atom, macho_file: *MachO) macho.se
555 return sect;555 return sect;
556}556}
557557
558pub fn flush(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.File.FlushError!void {558pub fn flush(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.Error!void {
559 const diags = &macho_file.base.comp.link_diags;559 const diags = &macho_file.base.comp.link_diags;
560560
561 // Handle any lazy symbols that were emitted by incremental compilation.561 // Handle any lazy symbols that were emitted by incremental compilation.
...@@ -571,7 +571,7 @@ pub fn flush(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.F...@@ -571,7 +571,7 @@ pub fn flush(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.F
571 .{ .kind = .code, .ty = .anyerror_type },571 .{ .kind = .code, .ty = .anyerror_type },
572 metadata.text_symbol_index,572 metadata.text_symbol_index,
573 ) catch |err| switch (err) {573 ) catch |err| switch (err) {
574 error.OutOfMemory, error.LinkFailure => |e| return e,574 error.OutOfMemory, error.AlreadyReported => |e| return e,
575 else => |e| return diags.fail("failed to update lazy symbol: {s}", .{@errorName(e)}),575 else => |e| return diags.fail("failed to update lazy symbol: {s}", .{@errorName(e)}),
576 };576 };
577 if (metadata.const_state != .unused) self.updateLazySymbol(577 if (metadata.const_state != .unused) self.updateLazySymbol(
...@@ -580,7 +580,7 @@ pub fn flush(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.F...@@ -580,7 +580,7 @@ pub fn flush(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.F
580 .{ .kind = .const_data, .ty = .anyerror_type },580 .{ .kind = .const_data, .ty = .anyerror_type },
581 metadata.const_symbol_index,581 metadata.const_symbol_index,
582 ) catch |err| switch (err) {582 ) catch |err| switch (err) {
583 error.OutOfMemory, error.LinkFailure => |e| return e,583 error.OutOfMemory, error.AlreadyReported => |e| return e,
584 else => |e| return diags.fail("failed to update lazy symbol: {s}", .{@errorName(e)}),584 else => |e| return diags.fail("failed to update lazy symbol: {s}", .{@errorName(e)}),
585 };585 };
586 }586 }
...@@ -704,8 +704,7 @@ pub fn lowerUav(...@@ -704,8 +704,7 @@ pub fn lowerUav(
704 pt: Zcu.PerThread,704 pt: Zcu.PerThread,
705 uav: InternPool.Index,705 uav: InternPool.Index,
706 explicit_alignment: Atom.Alignment,706 explicit_alignment: Atom.Alignment,
707 src_loc: Zcu.LazySrcLoc,707) !link.File.SymbolId {
708) !codegen.SymbolResult {
709 const zcu = pt.zcu;708 const zcu = pt.zcu;
710 const gpa = zcu.gpa;709 const gpa = zcu.gpa;
711 const val = Value.fromInterned(uav);710 const val = Value.fromInterned(uav);
...@@ -717,35 +716,29 @@ pub fn lowerUav(...@@ -717,35 +716,29 @@ pub fn lowerUav(
717 const sym = self.symbols.items[metadata.symbol_index];716 const sym = self.symbols.items[metadata.symbol_index];
718 const existing_alignment = sym.getAtom(macho_file).?.alignment;717 const existing_alignment = sym.getAtom(macho_file).?.alignment;
719 if (uav_alignment.order(existing_alignment).compare(.lte))718 if (uav_alignment.order(existing_alignment).compare(.lte))
720 return .{ .sym_index = @enumFromInt(metadata.symbol_index) };719 return @enumFromInt(metadata.symbol_index);
721 }720 }
722721
723 var name_buf: [32]u8 = undefined;722 var name_buf: [32]u8 = undefined;
724 const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{723 const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{
725 @intFromEnum(uav),724 @intFromEnum(uav),
726 }) catch unreachable;725 }) catch unreachable;
727 const res = self.lowerConst(726 const sym_index = self.lowerConst(
728 macho_file,727 macho_file,
729 pt,728 pt,
730 name,729 name,
731 val,730 val,
732 uav_alignment,731 uav_alignment,
733 macho_file.zig_const_sect_index.?,732 macho_file.zig_const_sect_index.?,
734 src_loc,
735 ) catch |err| switch (err) {733 ) catch |err| switch (err) {
736 error.OutOfMemory => |e| return e,734 error.OutOfMemory => |e| return e,
737 else => |e| return .{ .fail = try Zcu.ErrorMsg.create(735 else => |e| return macho_file.base.comp.link_diags.fail(
738 gpa,736 "failed to lower constant value: {t}",
739 src_loc,737 .{e},
740 "unable to lower constant value: {s}",738 ),
741 .{@errorName(e)},
742 ) },
743 };739 };
744 switch (res) {740 try self.uavs.put(gpa, uav, .{ .symbol_index = @intFromEnum(sym_index) });
745 .sym_index => |sym_index| try self.uavs.put(gpa, uav, .{ .symbol_index = @intFromEnum(sym_index) }),741 return sym_index;
746 .fail => {},
747 }
748 return res;
749}742}
750743
751fn freeNavMetadata(self: *ZigObject, macho_file: *MachO, sym_index: Symbol.Index) void {744fn freeNavMetadata(self: *ZigObject, macho_file: *MachO, sym_index: Symbol.Index) void {
...@@ -776,7 +769,7 @@ pub fn updateFunc(...@@ -776,7 +769,7 @@ pub fn updateFunc(
776 pt: Zcu.PerThread,769 pt: Zcu.PerThread,
777 func_index: InternPool.Index,770 func_index: InternPool.Index,
778 mir: *const codegen.AnyMir,771 mir: *const codegen.AnyMir,
779) link.File.UpdateNavError!void {772) link.Error!void {
780 const tracy = trace(@src());773 const tracy = trace(@src());
781 defer tracy.end();774 defer tracy.end();
782775
...@@ -796,7 +789,6 @@ pub fn updateFunc(...@@ -796,7 +789,6 @@ pub fn updateFunc(
796 codegen.emitFunction(789 codegen.emitFunction(
797 &macho_file.base,790 &macho_file.base,
798 pt,791 pt,
799 zcu.navSrcLoc(func.owner_nav),
800 func_index,792 func_index,
801 @enumFromInt(sym_index),793 @enumFromInt(sym_index),
802 mir,794 mir,
...@@ -867,7 +859,7 @@ pub fn updateNav(...@@ -867,7 +859,7 @@ pub fn updateNav(
867 macho_file: *MachO,859 macho_file: *MachO,
868 pt: Zcu.PerThread,860 pt: Zcu.PerThread,
869 nav_index: InternPool.Nav.Index,861 nav_index: InternPool.Nav.Index,
870) link.File.UpdateNavError!void {862) link.Error!void {
871 const tracy = trace(@src());863 const tracy = trace(@src());
872 defer tracy.end();864 defer tracy.end();
873865
...@@ -887,7 +879,7 @@ pub fn updateNav(...@@ -887,7 +879,7 @@ pub fn updateNav(
887 var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, @enumFromInt(sym_index));879 var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, @enumFromInt(sym_index));
888 defer debug_wip_nav.deinit();880 defer debug_wip_nav.deinit();
889 dwarf.finishWipNav(pt, nav_index, &debug_wip_nav) catch |err| switch (err) {881 dwarf.finishWipNav(pt, nav_index, &debug_wip_nav) catch |err| switch (err) {
890 error.OutOfMemory, error.Overflow => |e| return e,882 error.OutOfMemory, error.Canceled, error.AlreadyReported => |e| return e,
891 else => |e| return macho_file.base.cgFail(nav_index, "failed to finish dwarf nav: {s}", .{@errorName(e)}),883 else => |e| return macho_file.base.cgFail(nav_index, "failed to finish dwarf nav: {s}", .{@errorName(e)}),
892 };884 };
893 }885 }
...@@ -908,7 +900,6 @@ pub fn updateNav(...@@ -908,7 +900,6 @@ pub fn updateNav(
908 codegen.generateSymbol(900 codegen.generateSymbol(
909 &macho_file.base,901 &macho_file.base,
910 pt,902 pt,
911 zcu.navSrcLoc(nav_index),
912 .fromInterned(nav.resolved.?.value),903 .fromInterned(nav.resolved.?.value),
913 &aw.writer,904 &aw.writer,
914 .{ .atom_index = @enumFromInt(sym_index) },905 .{ .atom_index = @enumFromInt(sym_index) },
...@@ -925,7 +916,7 @@ pub fn updateNav(...@@ -925,7 +916,7 @@ pub fn updateNav(
925 try self.updateNavCode(macho_file, pt, nav_index, sym_index, sect_index, code);916 try self.updateNavCode(macho_file, pt, nav_index, sym_index, sect_index, code);
926917
927 if (debug_wip_nav) |*wip_nav| self.dwarf.?.finishWipNav(pt, nav_index, wip_nav) catch |err| switch (err) {918 if (debug_wip_nav) |*wip_nav| self.dwarf.?.finishWipNav(pt, nav_index, wip_nav) catch |err| switch (err) {
928 error.OutOfMemory, error.Overflow => |e| return e,919 error.OutOfMemory, error.Canceled, error.AlreadyReported => |e| return e,
929 else => |e| return macho_file.base.cgFail(nav_index, "failed to finish dwarf nav: {s}", .{@errorName(e)}),920 else => |e| return macho_file.base.cgFail(nav_index, "failed to finish dwarf nav: {s}", .{@errorName(e)}),
930 };921 };
931 } else if (self.dwarf) |*dwarf| try dwarf.updateComptimeNav(pt, nav_index);922 } else if (self.dwarf) |*dwarf| try dwarf.updateComptimeNav(pt, nav_index);
...@@ -941,7 +932,7 @@ fn updateNavCode(...@@ -941,7 +932,7 @@ fn updateNavCode(
941 sym_index: Symbol.Index,932 sym_index: Symbol.Index,
942 sect_index: u8,933 sect_index: u8,
943 code: []const u8,934 code: []const u8,
944) link.File.UpdateNavError!void {935) link.Error!void {
945 const zcu = pt.zcu;936 const zcu = pt.zcu;
946 const gpa = zcu.gpa;937 const gpa = zcu.gpa;
947 const comp = zcu.comp;938 const comp = zcu.comp;
...@@ -1198,8 +1189,7 @@ fn lowerConst(...@@ -1198,8 +1189,7 @@ fn lowerConst(
1198 val: Value,1189 val: Value,
1199 required_alignment: Atom.Alignment,1190 required_alignment: Atom.Alignment,
1200 output_section_index: u8,1191 output_section_index: u8,
1201 src_loc: Zcu.LazySrcLoc,1192) !link.File.SymbolId {
1202) !codegen.SymbolResult {
1203 const gpa = macho_file.base.comp.gpa;1193 const gpa = macho_file.base.comp.gpa;
12041194
1205 var aw: std.Io.Writer.Allocating = .init(gpa);1195 var aw: std.Io.Writer.Allocating = .init(gpa);
...@@ -1211,7 +1201,6 @@ fn lowerConst(...@@ -1211,7 +1201,6 @@ fn lowerConst(
1211 codegen.generateSymbol(1201 codegen.generateSymbol(
1212 &macho_file.base,1202 &macho_file.base,
1213 pt,1203 pt,
1214 src_loc,
1215 val,1204 val,
1216 &aw.writer,1205 &aw.writer,
1217 .{ .atom_index = @enumFromInt(sym_index) },1206 .{ .atom_index = @enumFromInt(sym_index) },
...@@ -1242,7 +1231,7 @@ fn lowerConst(...@@ -1242,7 +1231,7 @@ fn lowerConst(
1242 const file_offset = sect.offset + atom.value;1231 const file_offset = sect.offset + atom.value;
1243 try macho_file.pwriteAll(code, file_offset);1232 try macho_file.pwriteAll(code, file_offset);
12441233
1245 return .{ .sym_index = @enumFromInt(sym_index) };1234 return @enumFromInt(sym_index);
1246}1235}
12471236
1248pub fn updateExports(1237pub fn updateExports(
...@@ -1251,7 +1240,7 @@ pub fn updateExports(...@@ -1251,7 +1240,7 @@ pub fn updateExports(
1251 pt: Zcu.PerThread,1240 pt: Zcu.PerThread,
1252 exported: Zcu.Exported,1241 exported: Zcu.Exported,
1253 export_indices: []const Zcu.Export.Index,1242 export_indices: []const Zcu.Export.Index,
1254) link.File.UpdateExportsError!void {1243) link.Error!void {
1255 const tracy = trace(@src());1244 const tracy = trace(@src());
1256 defer tracy.end();1245 defer tracy.end();
12571246
...@@ -1263,18 +1252,7 @@ pub fn updateExports(...@@ -1263,18 +1252,7 @@ pub fn updateExports(
1263 break :blk self.navs.getPtr(nav).?;1252 break :blk self.navs.getPtr(nav).?;
1264 },1253 },
1265 .uav => |uav| self.uavs.getPtr(uav) orelse blk: {1254 .uav => |uav| self.uavs.getPtr(uav) orelse blk: {
1266 const first_exp = export_indices[0].ptr(zcu);1255 _ = try self.lowerUav(macho_file, pt, uav, .none);
1267 const res = try self.lowerUav(macho_file, pt, uav, .none, first_exp.src);
1268 switch (res) {
1269 .sym_index => {},
1270 .fail => |em| {
1271 // TODO maybe it's enough to return an error here and let Zcu.processExportsInner
1272 // handle the error?
1273 try zcu.failed_exports.ensureUnusedCapacity(zcu.gpa, 1);
1274 zcu.failed_exports.putAssumeCapacityNoClobber(export_indices[0], em);
1275 return;
1276 },
1277 }
1278 break :blk self.uavs.getPtr(uav).?;1256 break :blk self.uavs.getPtr(uav).?;
1279 },1257 },
1280 };1258 };
...@@ -1368,11 +1346,9 @@ fn updateLazySymbol(...@@ -1368,11 +1346,9 @@ fn updateLazySymbol(
1368 break :blk try self.addString(gpa, name);1346 break :blk try self.addString(gpa, name);
1369 };1347 };
13701348
1371 const src = Type.fromInterned(lazy_sym.ty).srcLocOrNull(zcu) orelse Zcu.LazySrcLoc.unneeded;
1372 try codegen.generateLazySymbol(1349 try codegen.generateLazySymbol(
1373 &macho_file.base,1350 &macho_file.base,
1374 pt,1351 pt,
1375 src,
1376 lazy_sym,1352 lazy_sym,
1377 &required_alignment,1353 &required_alignment,
1378 &aw.writer,1354 &aw.writer,
...@@ -1413,12 +1389,12 @@ fn updateLazySymbol(...@@ -1413,12 +1389,12 @@ fn updateLazySymbol(
1413 try macho_file.pwriteAll(code, file_offset);1389 try macho_file.pwriteAll(code, file_offset);
1414}1390}
14151391
1416pub fn updateLineNumber(self: *ZigObject, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {1392pub fn updateLineNumber(self: *ZigObject, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) link.Error!void {
1417 if (self.dwarf) |*dwarf| {1393 if (self.dwarf) |*dwarf| {
1418 const comp = dwarf.bin_file.comp;1394 const comp = dwarf.bin_file.comp;
1419 const diags = &comp.link_diags;1395 const diags = &comp.link_diags;
1420 dwarf.updateLineNumber(pt.zcu, ti_id) catch |err| switch (err) {1396 dwarf.updateLineNumber(pt.zcu, ti_id) catch |err| switch (err) {
1421 error.Overflow, error.OutOfMemory => |e| return e,1397 error.OutOfMemory, error.Canceled, error.AlreadyReported => |e| return e,
1422 else => |e| return diags.fail("failed to update dwarf line numbers: {s}", .{@errorName(e)}),1398 else => |e| return diags.fail("failed to update dwarf line numbers: {s}", .{@errorName(e)}),
1423 };1399 };
1424 }1400 }
src/link/MachO/relocatable.zig+13-13
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Path) link.File.FlushError!void {1pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Path) link.Error!void {
2 const gpa = comp.gpa;2 const gpa = comp.gpa;
3 const io = comp.io;3 const io = comp.io;
4 const diags = &comp.link_diags;4 const diags = &comp.link_diags;
...@@ -34,15 +34,15 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat...@@ -34,15 +34,15 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat
34 diags.addParseError(link_input.path().?, "failed to read input file: {s}", .{@errorName(err)});34 diags.addParseError(link_input.path().?, "failed to read input file: {s}", .{@errorName(err)});
35 }35 }
3636
37 if (diags.hasErrors()) return error.LinkFailure;37 if (diags.hasErrors()) return error.AlreadyReported;
3838
39 try macho_file.parseInputFiles();39 try macho_file.parseInputFiles();
4040
41 if (diags.hasErrors()) return error.LinkFailure;41 if (diags.hasErrors()) return error.AlreadyReported;
4242
43 try macho_file.resolveSymbols();43 try macho_file.resolveSymbols();
44 macho_file.dedupLiterals() catch |err| switch (err) {44 macho_file.dedupLiterals() catch |err| switch (err) {
45 error.OutOfMemory, error.LinkFailure => |e| return e,45 error.OutOfMemory, error.AlreadyReported => |e| return e,
46 else => |e| return diags.fail("failed to update ar size: {s}", .{@errorName(e)}),46 else => |e| return diags.fail("failed to update ar size: {s}", .{@errorName(e)}),
47 };47 };
48 markExports(macho_file);48 markExports(macho_file);
...@@ -54,7 +54,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat...@@ -54,7 +54,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat
5454
55 try createSegment(macho_file);55 try createSegment(macho_file);
56 allocateSections(macho_file) catch |err| switch (err) {56 allocateSections(macho_file) catch |err| switch (err) {
57 error.LinkFailure => |e| return e,57 error.AlreadyReported => |e| return e,
58 else => |e| return diags.fail("failed to allocate sections: {s}", .{@errorName(e)}),58 else => |e| return diags.fail("failed to allocate sections: {s}", .{@errorName(e)}),
59 };59 };
60 allocateSegment(macho_file);60 allocateSegment(macho_file);
...@@ -75,7 +75,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat...@@ -75,7 +75,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat
75 try writeHeader(macho_file, ncmds, sizeofcmds);75 try writeHeader(macho_file, ncmds, sizeofcmds);
76}76}
7777
78pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Path) link.File.FlushError!void {78pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Path) link.Error!void {
79 const gpa = comp.gpa;79 const gpa = comp.gpa;
80 const io = comp.io;80 const io = comp.io;
81 const diags = &macho_file.base.comp.link_diags;81 const diags = &macho_file.base.comp.link_diags;
...@@ -105,11 +105,11 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?...@@ -105,11 +105,11 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?
105 diags.addParseError(link_input.path().?, "failed to read input file: {s}", .{@errorName(err)});105 diags.addParseError(link_input.path().?, "failed to read input file: {s}", .{@errorName(err)});
106 }106 }
107107
108 if (diags.hasErrors()) return error.LinkFailure;108 if (diags.hasErrors()) return error.AlreadyReported;
109109
110 try parseInputFilesAr(macho_file);110 try parseInputFilesAr(macho_file);
111111
112 if (diags.hasErrors()) return error.LinkFailure;112 if (diags.hasErrors()) return error.AlreadyReported;
113113
114 // First, we flush relocatable object file generated with our backends.114 // First, we flush relocatable object file generated with our backends.
115 if (macho_file.getZigObject()) |zo| {115 if (macho_file.getZigObject()) |zo| {
...@@ -231,7 +231,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?...@@ -231,7 +231,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?
231 try macho_file.setLength(total_size);231 try macho_file.setLength(total_size);
232 try macho_file.pwriteAll(writer.buffered(), 0);232 try macho_file.pwriteAll(writer.buffered(), 0);
233233
234 if (diags.hasErrors()) return error.LinkFailure;234 if (diags.hasErrors()) return error.AlreadyReported;
235}235}
236236
237fn parseInputFilesAr(macho_file: *MachO) !void {237fn parseInputFilesAr(macho_file: *MachO) !void {
...@@ -339,7 +339,7 @@ fn calcSectionSizes(macho_file: *MachO) !void {...@@ -339,7 +339,7 @@ fn calcSectionSizes(macho_file: *MachO) !void {
339 }339 }
340 try calcSymtabSize(macho_file);340 try calcSymtabSize(macho_file);
341341
342 if (diags.hasErrors()) return error.LinkFailure;342 if (diags.hasErrors()) return error.AlreadyReported;
343}343}
344344
345fn calcSectionSizeWorker(macho_file: *MachO, sect_id: u8) void {345fn calcSectionSizeWorker(macho_file: *MachO, sect_id: u8) void {
...@@ -586,7 +586,7 @@ fn sortRelocs(macho_file: *MachO) void {...@@ -586,7 +586,7 @@ fn sortRelocs(macho_file: *MachO) void {
586 }586 }
587}587}
588588
589fn writeSections(macho_file: *MachO) link.File.FlushError!void {589fn writeSections(macho_file: *MachO) link.Error!void {
590 const tracy = trace(@src());590 const tracy = trace(@src());
591 defer tracy.end();591 defer tracy.end();
592592
...@@ -632,7 +632,7 @@ fn writeSections(macho_file: *MachO) link.File.FlushError!void {...@@ -632,7 +632,7 @@ fn writeSections(macho_file: *MachO) link.File.FlushError!void {
632 }632 }
633 }633 }
634634
635 if (diags.hasErrors()) return error.LinkFailure;635 if (diags.hasErrors()) return error.AlreadyReported;
636636
637 if (macho_file.getZigObject()) |zo| {637 if (macho_file.getZigObject()) |zo| {
638 try zo.writeRelocs(macho_file);638 try zo.writeRelocs(macho_file);
...@@ -685,7 +685,7 @@ fn writeSectionsToFile(macho_file: *MachO) !void {...@@ -685,7 +685,7 @@ fn writeSectionsToFile(macho_file: *MachO) !void {
685 try macho_file.pwriteAll(macho_file.strtab.items, macho_file.symtab_cmd.stroff);685 try macho_file.pwriteAll(macho_file.strtab.items, macho_file.symtab_cmd.stroff);
686}686}
687687
688fn writeLoadCommands(macho_file: *MachO) error{ LinkFailure, OutOfMemory }!struct { usize, usize } {688fn writeLoadCommands(macho_file: *MachO) error{ AlreadyReported, OutOfMemory }!struct { usize, usize } {
689 const gpa = macho_file.base.comp.gpa;689 const gpa = macho_file.base.comp.gpa;
690 const needed_size = load_commands.calcLoadCommandsSizeObject(macho_file);690 const needed_size = load_commands.calcLoadCommandsSizeObject(macho_file);
691 const buffer = try gpa.alloc(u8, needed_size);691 const buffer = try gpa.alloc(u8, needed_size);
src/link/MappedFile.zig+154-45
...@@ -5,6 +5,7 @@ const is_linux = builtin.os.tag == .linux;...@@ -5,6 +5,7 @@ const is_linux = builtin.os.tag == .linux;
5const is_windows = builtin.os.tag == .windows;5const is_windows = builtin.os.tag == .windows;
66
7const std = @import("std");7const std = @import("std");
8const Allocator = std.mem.Allocator;
8const Io = std.Io;9const Io = std.Io;
9const assert = std.debug.assert;10const assert = std.debug.assert;
10const linux = std.os.linux;11const linux = std.os.linux;
...@@ -24,14 +25,40 @@ large: std.ArrayList(u64),...@@ -24,14 +25,40 @@ large: std.ArrayList(u64),
24updates: std.ArrayList(Node.Index),25updates: std.ArrayList(Node.Index),
25update_prog_node: std.Progress.Node,26update_prog_node: std.Progress.Node,
26writers: std.SinglyLinkedList,27writers: std.SinglyLinkedList,
28io_err: ?IoError,
2729
28pub const growth_factor = 4;30pub const growth_factor = 4;
2931
30pub const Error = error{32pub const IoError = Io.UnexpectedError || error{
33 DiskQuota,
34 FileTooBig,
35 InputOutput,
36 NoSpaceLeft,
37 AccessDenied,
38 PermissionDenied,
39 SystemResources,
40 LockViolation,
41 LockedMemoryLimitExceeded,
42 ProcessFdQuotaExceeded,
43 SystemFdQuotaExceeded,
44 FileBusy,
45 DeviceBusy,
46 NoDevice,
47 PathAlreadyExists,
48 IsDir,
31 NotFile,49 NotFile,
32} || Io.File.MemoryMap.CreateError || Io.File.MemoryMap.SetLengthError || Io.File.WritePositionalError;50 BrokenPipe,
51 NonResizable,
52 Unseekable,
53};
54
55pub const Error = Allocator.Error || Io.Cancelable || error{
56 /// Some I/O operation on the memory-mapped file failed. The underlying error is available in
57 /// the `MappedFile.io_err` field.
58 MappedFileIo,
59};
3360
34pub fn init(file: Io.File, gpa: std.mem.Allocator, io: Io) !MappedFile {61pub fn init(file: Io.File, gpa: std.mem.Allocator, io: Io) (Allocator.Error || Io.Cancelable || IoError)!MappedFile {
35 var mf: MappedFile = .{62 var mf: MappedFile = .{
36 .io = io,63 .io = io,
37 .flags = undefined,64 .flags = undefined,
...@@ -47,10 +74,14 @@ pub fn init(file: Io.File, gpa: std.mem.Allocator, io: Io) !MappedFile {...@@ -47,10 +74,14 @@ pub fn init(file: Io.File, gpa: std.mem.Allocator, io: Io) !MappedFile {
47 .updates = .empty,74 .updates = .empty,
48 .update_prog_node = .none,75 .update_prog_node = .none,
49 .writers = .{},76 .writers = .{},
77 .io_err = null,
50 };78 };
51 errdefer mf.deinit(gpa);79 errdefer mf.deinit(gpa);
52 const size: u64, const block_size = stat: {80 const size: u64, const block_size = stat: {
53 const stat = try file.stat(io);81 const stat = file.stat(io) catch |err| switch (err) {
82 error.Streaming => return error.PathAlreadyExists,
83 else => |e| return e,
84 };
54 if (stat.kind != .file) return error.PathAlreadyExists;85 if (stat.kind != .file) return error.PathAlreadyExists;
55 break :stat .{ stat.size, @max(std.heap.pageSize(), stat.block_size) };86 break :stat .{ stat.size, @max(std.heap.pageSize(), stat.block_size) };
56 };87 };
...@@ -61,14 +92,16 @@ pub fn init(file: Io.File, gpa: std.mem.Allocator, io: Io) !MappedFile {...@@ -61,14 +92,16 @@ pub fn init(file: Io.File, gpa: std.mem.Allocator, io: Io) !MappedFile {
61 .fallocate_punch_hole_unsupported = false,92 .fallocate_punch_hole_unsupported = false,
62 };93 };
63 try mf.nodes.ensureUnusedCapacity(gpa, 1);94 try mf.nodes.ensureUnusedCapacity(gpa, 1);
64 assert(try mf.addNode(gpa, .{95 const root_ni = mf.addNode(gpa, .{ .add_node = .{
65 .add_node = .{96 .size = size,
66 .size = size,97 .alignment = mf.flags.block_size,
67 .alignment = mf.flags.block_size,98 .fixed = true,
68 .fixed = true,99 } }) catch |err| switch (err) {
69 },100 error.MappedFileIo => return mf.io_err.?,
70 }) == Node.Index.root);101 else => |e| return e,
71 try mf.ensureTotalCapacity(@intCast(size));102 };
103 assert(root_ni == Node.Index.root);
104 try mf.ensureTotalCapacityInner(@intCast(size));
72 return mf;105 return mf;
73}106}
74107
...@@ -174,7 +207,7 @@ pub const Node = extern struct {...@@ -174,7 +207,7 @@ pub const Node = extern struct {
174 return .{ .mf = mf, .ni = ni.get(mf).last };207 return .{ .mf = mf, .ni = ni.get(mf).last };
175 }208 }
176209
177 pub fn childrenMoved(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) !void {210 pub fn childrenMoved(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) Allocator.Error!void {
178 var child_ni = ni.get(mf).last;211 var child_ni = ni.get(mf).last;
179 while (child_ni != .none) {212 while (child_ni != .none) {
180 try child_ni.moved(gpa, mf);213 try child_ni.moved(gpa, mf);
...@@ -192,7 +225,7 @@ pub const Node = extern struct {...@@ -192,7 +225,7 @@ pub const Node = extern struct {
192 }225 }
193 return false;226 return false;
194 }227 }
195 pub fn moved(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) !void {228 pub fn moved(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) Allocator.Error!void {
196 try mf.updates.ensureUnusedCapacity(gpa, 1);229 try mf.updates.ensureUnusedCapacity(gpa, 1);
197 ni.movedAssumeCapacity(mf);230 ni.movedAssumeCapacity(mf);
198 }231 }
...@@ -213,7 +246,7 @@ pub const Node = extern struct {...@@ -213,7 +246,7 @@ pub const Node = extern struct {
213 pub fn hasResized(ni: Node.Index, mf: *const MappedFile) bool {246 pub fn hasResized(ni: Node.Index, mf: *const MappedFile) bool {
214 return ni.get(mf).flags.resized;247 return ni.get(mf).flags.resized;
215 }248 }
216 pub fn resized(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) !void {249 pub fn resized(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) Allocator.Error!void {
217 try mf.updates.ensureUnusedCapacity(gpa, 1);250 try mf.updates.ensureUnusedCapacity(gpa, 1);
218 ni.resizedAssumeCapacity(mf);251 ni.resizedAssumeCapacity(mf);
219 }252 }
...@@ -296,8 +329,16 @@ pub const Node = extern struct {...@@ -296,8 +329,16 @@ pub const Node = extern struct {
296 return mf.memory_map.memory[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)];329 return mf.memory_map.memory[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)];
297 }330 }
298331
299 pub fn resize(ni: Node.Index, mf: *MappedFile, gpa: std.mem.Allocator, size: u64) !void {332 pub fn resize(ni: Node.Index, mf: *MappedFile, gpa: std.mem.Allocator, size: u64) Error!void {
300 try mf.resizeNode(gpa, ni, size);333 mf.resizeNode(gpa, ni, size) catch |err| switch (err) {
334 error.OutOfMemory,
335 error.Canceled,
336 => |e| return e,
337 else => |e| {
338 mf.io_err = e;
339 return error.MappedFileIo;
340 },
341 };
301 var writers_it = mf.writers.first;342 var writers_it = mf.writers.first;
302 while (writers_it) |writer_node| : (writers_it = writer_node.next) {343 while (writers_it) |writer_node| : (writers_it = writer_node.next) {
303 const w: *Node.Writer = @fieldParentPtr("writer_node", writer_node);344 const w: *Node.Writer = @fieldParentPtr("writer_node", writer_node);
...@@ -313,8 +354,16 @@ pub const Node = extern struct {...@@ -313,8 +354,16 @@ pub const Node = extern struct {
313 mf: *MappedFile,354 mf: *MappedFile,
314 gpa: std.mem.Allocator,355 gpa: std.mem.Allocator,
315 new_alignment: std.mem.Alignment,356 new_alignment: std.mem.Alignment,
316 ) !void {357 ) Error!void {
317 try mf.realignNode(gpa, ni, new_alignment);358 mf.realignNode(gpa, ni, new_alignment) catch |err| switch (err) {
359 error.OutOfMemory,
360 error.Canceled,
361 => |e| return e,
362 else => |e| {
363 mf.io_err = e;
364 return error.MappedFileIo;
365 },
366 };
318 var writers_it = mf.writers.first;367 var writers_it = mf.writers.first;
319 while (writers_it) |writer_node| : (writers_it = writer_node.next) {368 while (writers_it) |writer_node| : (writers_it = writer_node.next) {
320 const w: *Node.Writer = @fieldParentPtr("writer_node", writer_node);369 const w: *Node.Writer = @fieldParentPtr("writer_node", writer_node);
...@@ -422,9 +471,16 @@ pub const Node = extern struct {...@@ -422,9 +471,16 @@ pub const Node = extern struct {
422 file_reader.pos,471 file_reader.pos,
423 w.ni.fileLocation(w.mf, true).offset + interface.end,472 w.ni.fileLocation(w.mf, true).offset + interface.end,
424 limit.minInt(interface.unusedCapacityLen()),473 limit.minInt(interface.unusedCapacityLen()),
425 ) catch |err| {474 ) catch |err| switch (err) {
426 w.err = err;475 error.Canceled => |e| {
427 return error.WriteFailed;476 w.err = e;
477 return error.WriteFailed;
478 },
479 else => |e| {
480 w.mf.io_err = e;
481 w.err = error.MappedFileIo;
482 return error.WriteFailed;
483 },
428 });484 });
429 if (n == 0) return error.Unimplemented;485 if (n == 0) return error.Unimplemented;
430 file_reader.pos += n;486 file_reader.pos += n;
...@@ -472,7 +528,7 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {...@@ -472,7 +528,7 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {
472 next: Node.Index = .none,528 next: Node.Index = .none,
473 offset: u64 = 0,529 offset: u64 = 0,
474 add_node: AddNodeOptions,530 add_node: AddNodeOptions,
475}) !Node.Index {531}) Error!Node.Index {
476 if (opts.add_node.moved or opts.add_node.resized) try mf.updates.ensureUnusedCapacity(gpa, 1);532 if (opts.add_node.moved or opts.add_node.resized) try mf.updates.ensureUnusedCapacity(gpa, 1);
477 const offset = opts.add_node.alignment.forward(@intCast(opts.offset));533 const offset = opts.add_node.alignment.forward(@intCast(opts.offset));
478 const location_tag: Node.Location.Tag, const location_payload: Node.Location.Payload = location: {534 const location_tag: Node.Location.Tag, const location_payload: Node.Location.Payload = location: {
...@@ -544,7 +600,7 @@ pub fn addOnlyChildNode(...@@ -544,7 +600,7 @@ pub fn addOnlyChildNode(
544 gpa: std.mem.Allocator,600 gpa: std.mem.Allocator,
545 parent_ni: Node.Index,601 parent_ni: Node.Index,
546 opts: AddNodeOptions,602 opts: AddNodeOptions,
547) !Node.Index {603) Error!Node.Index {
548 try mf.nodes.ensureUnusedCapacity(gpa, 1);604 try mf.nodes.ensureUnusedCapacity(gpa, 1);
549 const parent = parent_ni.get(mf);605 const parent = parent_ni.get(mf);
550 assert(parent.first == .none and parent.last == .none);606 assert(parent.first == .none and parent.last == .none);
...@@ -559,7 +615,7 @@ pub fn addFirstChildNode(...@@ -559,7 +615,7 @@ pub fn addFirstChildNode(
559 gpa: std.mem.Allocator,615 gpa: std.mem.Allocator,
560 parent_ni: Node.Index,616 parent_ni: Node.Index,
561 opts: AddNodeOptions,617 opts: AddNodeOptions,
562) !Node.Index {618) Error!Node.Index {
563 try mf.nodes.ensureUnusedCapacity(gpa, 1);619 try mf.nodes.ensureUnusedCapacity(gpa, 1);
564 const parent = parent_ni.get(mf);620 const parent = parent_ni.get(mf);
565 return mf.addNode(gpa, .{621 return mf.addNode(gpa, .{
...@@ -574,7 +630,7 @@ pub fn addLastChildNode(...@@ -574,7 +630,7 @@ pub fn addLastChildNode(
574 gpa: std.mem.Allocator,630 gpa: std.mem.Allocator,
575 parent_ni: Node.Index,631 parent_ni: Node.Index,
576 opts: AddNodeOptions,632 opts: AddNodeOptions,
577) !Node.Index {633) Error!Node.Index {
578 try mf.nodes.ensureUnusedCapacity(gpa, 1);634 try mf.nodes.ensureUnusedCapacity(gpa, 1);
579 const parent = parent_ni.get(mf);635 const parent = parent_ni.get(mf);
580 return mf.addNode(gpa, .{636 return mf.addNode(gpa, .{
...@@ -596,7 +652,7 @@ pub fn addNodeAfter(...@@ -596,7 +652,7 @@ pub fn addNodeAfter(
596 gpa: std.mem.Allocator,652 gpa: std.mem.Allocator,
597 prev_ni: Node.Index,653 prev_ni: Node.Index,
598 opts: AddNodeOptions,654 opts: AddNodeOptions,
599) !Node.Index {655) Error!Node.Index {
600 assert(prev_ni != .none);656 assert(prev_ni != .none);
601 try mf.nodes.ensureUnusedCapacity(gpa, 1);657 try mf.nodes.ensureUnusedCapacity(gpa, 1);
602 const prev = prev_ni.get(mf);658 const prev = prev_ni.get(mf);
...@@ -610,7 +666,7 @@ pub fn addNodeAfter(...@@ -610,7 +666,7 @@ pub fn addNodeAfter(
610 });666 });
611}667}
612668
613fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested_size: u64) !void {669fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested_size: u64) (Allocator.Error || Io.Cancelable || IoError)!void {
614 const io = mf.io;670 const io = mf.io;
615 const node = ni.get(mf);671 const node = ni.get(mf);
616 const old_offset, const old_size = node.location().resolve(mf);672 const old_offset, const old_size = node.location().resolve(mf);
...@@ -618,9 +674,13 @@ fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested...@@ -618,9 +674,13 @@ fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested
618 // Resize the entire file674 // Resize the entire file
619 if (ni == Node.Index.root) {675 if (ni == Node.Index.root) {
620 try mf.ensureCapacityForSetLocation(gpa);676 try mf.ensureCapacityForSetLocation(gpa);
621 try mf.memory_map.write(io);677 mf.memory_map.write(io) catch |err| switch (err) {
678 error.WouldBlock => return error.Unexpected, // file was not opened as non-blocking
679 error.NotOpenForWriting => return error.Unexpected, // we definitely opened the file for writing
680 else => |e| return e,
681 };
622 try mf.memory_map.file.setLength(io, new_size);682 try mf.memory_map.file.setLength(io, new_size);
623 try mf.ensureTotalCapacity(@intCast(new_size));683 try mf.ensureTotalCapacityInner(@intCast(new_size));
624 ni.setLocationAssumeCapacity(mf, old_offset, new_size);684 ni.setLocationAssumeCapacity(mf, old_offset, new_size);
625 return;685 return;
626 }686 }
...@@ -643,7 +703,11 @@ fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested...@@ -643,7 +703,11 @@ fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested
643 if (is_linux and !mf.flags.fallocate_insert_range_unsupported and703 if (is_linux and !mf.flags.fallocate_insert_range_unsupported and
644 node.flags.alignment.order(mf.flags.block_size).compare(.gte))704 node.flags.alignment.order(mf.flags.block_size).compare(.gte))
645 insert_range: {705 insert_range: {
646 try mf.memory_map.write(io);706 mf.memory_map.write(io) catch |err| switch (err) {
707 error.WouldBlock => return error.Unexpected, // file was not opened as non-blocking
708 error.NotOpenForWriting => return error.Unexpected, // we definitely opened the file for writing
709 else => |e| return e,
710 };
647 // Ask the filesystem driver to insert extents into the file without copying any data711 // Ask the filesystem driver to insert extents into the file without copying any data
648 const last_offset, const last_size = parent.last.location(mf).resolve(mf);712 const last_offset, const last_size = parent.last.location(mf).resolve(mf);
649 const last_end = last_offset + last_size;713 const last_end = last_offset + last_size;
...@@ -674,7 +738,7 @@ fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested...@@ -674,7 +738,7 @@ fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested
674 enclosing_ni.setLocationAssumeCapacity(mf, enclosing_offset, new_enclosing_size);738 enclosing_ni.setLocationAssumeCapacity(mf, enclosing_offset, new_enclosing_size);
675 if (enclosing_ni == Node.Index.root) {739 if (enclosing_ni == Node.Index.root) {
676 assert(enclosing_offset == 0);740 assert(enclosing_offset == 0);
677 try mf.ensureTotalCapacity(@intCast(new_enclosing_size));741 try mf.ensureTotalCapacityInner(@intCast(new_enclosing_size));
678 break;742 break;
679 }743 }
680 var after_ni = enclosing.next;744 var after_ni = enclosing.next;
...@@ -865,7 +929,7 @@ fn realignNode(...@@ -865,7 +929,7 @@ fn realignNode(
865 gpa: std.mem.Allocator,929 gpa: std.mem.Allocator,
866 ni: Node.Index,930 ni: Node.Index,
867 new_alignment: std.mem.Alignment,931 new_alignment: std.mem.Alignment,
868) !void {932) (Allocator.Error || Io.Cancelable || IoError)!void {
869 assert(ni != Node.Index.root); // currently unsupported933 assert(ni != Node.Index.root); // currently unsupported
870934
871 const node = ni.get(mf);935 const node = ni.get(mf);
...@@ -936,7 +1000,7 @@ fn realignNode(...@@ -936,7 +1000,7 @@ fn realignNode(
936 }1000 }
937}1001}
9381002
939fn moveRange(mf: *MappedFile, old_file_offset: u64, new_file_offset: u64, size: u64) !void {1003fn moveRange(mf: *MappedFile, old_file_offset: u64, new_file_offset: u64, size: u64) (Io.Cancelable || IoError)!void {
940 // make a copy of this node at the new location1004 // make a copy of this node at the new location
941 try mf.copyRange(old_file_offset, new_file_offset, size);1005 try mf.copyRange(old_file_offset, new_file_offset, size);
942 // delete the copy of this node at the old location1006 // delete the copy of this node at the old location
...@@ -966,7 +1030,7 @@ fn moveRange(mf: *MappedFile, old_file_offset: u64, new_file_offset: u64, size:...@@ -966,7 +1030,7 @@ fn moveRange(mf: *MappedFile, old_file_offset: u64, new_file_offset: u64, size:
966 @memset(mf.memory_map.memory[@intCast(old_file_offset)..][0..@intCast(size)], 0);1030 @memset(mf.memory_map.memory[@intCast(old_file_offset)..][0..@intCast(size)], 0);
967}1031}
9681032
969fn copyRange(mf: *MappedFile, old_file_offset: u64, new_file_offset: u64, size: u64) !void {1033fn copyRange(mf: *MappedFile, old_file_offset: u64, new_file_offset: u64, size: u64) (Io.Cancelable || IoError)!void {
970 const copy_size = try mf.copyFileRange(mf.memory_map.file, old_file_offset, new_file_offset, size);1034 const copy_size = try mf.copyFileRange(mf.memory_map.file, old_file_offset, new_file_offset, size);
971 if (copy_size < size) @memcpy(1035 if (copy_size < size) @memcpy(
972 mf.memory_map.memory[@intCast(new_file_offset + copy_size)..][0..@intCast(size - copy_size)],1036 mf.memory_map.memory[@intCast(new_file_offset + copy_size)..][0..@intCast(size - copy_size)],
...@@ -980,9 +1044,13 @@ fn copyFileRange(...@@ -980,9 +1044,13 @@ fn copyFileRange(
980 old_file_offset: u64,1044 old_file_offset: u64,
981 new_file_offset: u64,1045 new_file_offset: u64,
982 size: u64,1046 size: u64,
983) !u64 {1047) (Io.Cancelable || IoError)!u64 {
984 const io = mf.io;1048 const io = mf.io;
985 try mf.memory_map.write(io);1049 mf.memory_map.write(io) catch |err| switch (err) {
1050 error.WouldBlock => return error.Unexpected, // file was not opened as non-blocking
1051 error.NotOpenForWriting => return error.Unexpected, // we definitely opened the file for writing
1052 else => |e| return e,
1053 };
986 var remaining_size = size;1054 var remaining_size = size;
987 if (is_linux and !mf.flags.copy_file_range_unsupported) {1055 if (is_linux and !mf.flags.copy_file_range_unsupported) {
988 var old_file_offset_mut: i64 = @intCast(old_file_offset);1056 var old_file_offset_mut: i64 = @intCast(old_file_offset);
...@@ -1021,17 +1089,41 @@ fn copyFileRange(...@@ -1021,17 +1089,41 @@ fn copyFileRange(
1021 return size - remaining_size;1089 return size - remaining_size;
1022}1090}
10231091
1024fn ensureCapacityForSetLocation(mf: *MappedFile, gpa: std.mem.Allocator) !void {1092fn ensureCapacityForSetLocation(mf: *MappedFile, gpa: std.mem.Allocator) Allocator.Error!void {
1025 try mf.large.ensureUnusedCapacity(gpa, 2);1093 try mf.large.ensureUnusedCapacity(gpa, 2);
1026 try mf.updates.ensureUnusedCapacity(gpa, 1);1094 try mf.updates.ensureUnusedCapacity(gpa, 1);
1027}1095}
10281096
1029pub fn ensureTotalCapacity(mf: *MappedFile, new_capacity: usize) !void {1097pub fn ensureTotalCapacity(mf: *MappedFile, new_capacity: usize) Error!void {
1098 mf.ensureTotalCapacityInner(new_capacity) catch |err| switch (err) {
1099 error.OutOfMemory,
1100 error.Canceled,
1101 => |e| return e,
1102
1103 else => |e| {
1104 mf.io_err = e;
1105 return error.MappedFileIo;
1106 },
1107 };
1108}
1109fn ensureTotalCapacityInner(mf: *MappedFile, new_capacity: usize) (Allocator.Error || Io.Cancelable || IoError)!void {
1030 if (mf.memory_map.memory.len >= new_capacity) return;1110 if (mf.memory_map.memory.len >= new_capacity) return;
1031 try mf.ensureTotalCapacityPrecise(new_capacity +| new_capacity / growth_factor);1111 try mf.ensureTotalCapacityPreciseInner(new_capacity +| new_capacity / growth_factor);
1032}1112}
10331113
1034pub fn ensureTotalCapacityPrecise(mf: *MappedFile, new_capacity: usize) !void {1114pub fn ensureTotalCapacityPrecise(mf: *MappedFile, new_capacity: usize) Error!void {
1115 mf.ensureTotalCapacityPreciseInner(new_capacity) catch |err| switch (err) {
1116 error.OutOfMemory,
1117 error.Canceled,
1118 => |e| return e,
1119
1120 else => |e| {
1121 mf.io_err = e;
1122 return error.MappedFileIo;
1123 },
1124 };
1125}
1126fn ensureTotalCapacityPreciseInner(mf: *MappedFile, new_capacity: usize) (Allocator.Error || Io.Cancelable || IoError)!void {
1035 if (mf.memory_map.memory.len >= new_capacity) return;1127 if (mf.memory_map.memory.len >= new_capacity) return;
1036 const io = mf.io;1128 const io = mf.io;
1037 const aligned_capacity = mf.flags.block_size.forward(new_capacity);1129 const aligned_capacity = mf.flags.block_size.forward(new_capacity);
...@@ -1047,7 +1139,11 @@ pub fn ensureTotalCapacityPrecise(mf: *MappedFile, new_capacity: usize) !void {...@@ -1047,7 +1139,11 @@ pub fn ensureTotalCapacityPrecise(mf: *MappedFile, new_capacity: usize) !void {
1047 }1139 }
10481140
1049 const file = mf.memory_map.file;1141 const file = mf.memory_map.file;
1050 mf.memory_map = try .create(io, file, .{ .len = aligned_capacity });1142 mf.memory_map = Io.File.MemoryMap.create(io, file, .{ .len = aligned_capacity }) catch |err| switch (err) {
1143 error.WouldBlock => return error.Unexpected, // file was not opened as non-blocking
1144 error.NotOpenForReading => return error.Unexpected, // we definitely opened the file for writing
1145 else => |e| return e,
1146 };
1051}1147}
10521148
1053pub fn unmap(mf: *MappedFile) void {1149pub fn unmap(mf: *MappedFile) void {
...@@ -1059,9 +1155,22 @@ pub fn unmap(mf: *MappedFile) void {...@@ -1059,9 +1155,22 @@ pub fn unmap(mf: *MappedFile) void {
1059 mf.memory_map.file = file;1155 mf.memory_map.file = file;
1060}1156}
10611157
1062pub fn flush(mf: *MappedFile) Io.File.WritePositionalError!void {1158pub fn flush(mf: *MappedFile) (Io.Cancelable || error{MappedFileIo})!void {
1063 const io = mf.io;1159 mf.memory_map.write(mf.io) catch |err| switch (err) {
1064 try mf.memory_map.write(io);1160 error.Canceled => |e| return e,
1161
1162 error.WouldBlock, // file was not opened as non-blocking
1163 error.NotOpenForWriting, // we definitely opened the file for writing
1164 => {
1165 mf.io_err = error.Unexpected;
1166 return error.MappedFileIo;
1167 },
1168
1169 else => |e| {
1170 mf.io_err = e;
1171 return error.MappedFileIo;
1172 },
1173 };
1065}1174}
10661175
1067fn verify(mf: *MappedFile) void {1176fn verify(mf: *MappedFile) void {
src/link/Queue.zig+7-3
...@@ -135,7 +135,7 @@ pub fn finishPrelinkQueue(q: *Queue, comp: *Compilation) Io.Cancelable!void {...@@ -135,7 +135,7 @@ pub fn finishPrelinkQueue(q: *Queue, comp: *Compilation) Io.Cancelable!void {
135 lf.post_prelink = true;135 lf.post_prelink = true;
136 } else |err| switch (err) {136 } else |err| switch (err) {
137 error.OutOfMemory => comp.link_diags.setAllocFailure(),137 error.OutOfMemory => comp.link_diags.setAllocFailure(),
138 error.LinkFailure => {},138 error.AlreadyReported => {},
139 error.Canceled => |e| return e,139 error.Canceled => |e| return e,
140 }140 }
141 }141 }
...@@ -178,7 +178,7 @@ fn runLinkTasks(q: *Queue, comp: *Compilation) void {...@@ -178,7 +178,7 @@ fn runLinkTasks(q: *Queue, comp: *Compilation) void {
178 } else |err| switch (err) {178 } else |err| switch (err) {
179 error.OutOfMemory => comp.link_diags.setAllocFailure(),179 error.OutOfMemory => comp.link_diags.setAllocFailure(),
180 error.Canceled => @panic("TODO"),180 error.Canceled => @panic("TODO"),
181 error.LinkFailure => {},181 error.AlreadyReported => {},
182 }182 }
183 }183 }
184 }184 }
...@@ -205,7 +205,11 @@ fn runIdleTask(comp: *Compilation, tid: Zcu.PerThread.Id) bool {...@@ -205,7 +205,11 @@ fn runIdleTask(comp: *Compilation, tid: Zcu.PerThread.Id) bool {
205 comp.link_diags.setAllocFailure();205 comp.link_diags.setAllocFailure();
206 break :have_more false;206 break :have_more false;
207 },207 },
208 error.LinkFailure => false,208 error.AlreadyReported => false,
209 error.Canceled => {
210 comp.io.recancel();
211 return false;
212 },
209 };213 };
210}214}
211215
src/link/SpirV.zig+4-15
...@@ -140,19 +140,8 @@ fn generate(...@@ -140,19 +140,8 @@ fn generate(
140 };140 };
141141
142 linker.cg.genNav(do_codegen) catch |err| switch (err) {142 linker.cg.genNav(do_codegen) catch |err| switch (err) {
143 error.CodegenFail => switch (zcu.codegenFailMsg(nav_index, linker.cg.error_msg.?)) {143 error.AlreadyReported => return,
144 error.CodegenFail => {},144 else => |e| return e,
145 error.OutOfMemory => |e| return e,
146 },
147 else => |other| {
148 // There might be an error that happened *after* linker.error_msg
149 // was already allocated, so be sure to free it.
150 if (linker.cg.error_msg) |error_msg| {
151 error_msg.deinit(gpa);
152 }
153
154 return other;
155 },
156 };145 };
157}146}
158147
...@@ -168,7 +157,7 @@ pub fn updateFunc(...@@ -168,7 +157,7 @@ pub fn updateFunc(
168 try linker.generate(pt, nav, air.*, liveness.*.?, true);157 try linker.generate(pt, nav, air.*, liveness.*.?, true);
169}158}
170159
171pub fn updateNav(linker: *Linker, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.File.UpdateNavError!void {160pub fn updateNav(linker: *Linker, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.Error!void {
172 const ip = &pt.zcu.intern_pool;161 const ip = &pt.zcu.intern_pool;
173 log.debug("lowering nav {f}({d})", .{ ip.getNav(nav).fqn.fmt(ip), nav });162 log.debug("lowering nav {f}({d})", .{ ip.getNav(nav).fqn.fmt(ip), nav });
174 try linker.generate(pt, nav, undefined, undefined, false);163 try linker.generate(pt, nav, undefined, undefined, false);
...@@ -231,7 +220,7 @@ pub fn flush(...@@ -231,7 +220,7 @@ pub fn flush(
231 arena: Allocator,220 arena: Allocator,
232 tid: Zcu.PerThread.Id,221 tid: Zcu.PerThread.Id,
233 prog_node: std.Progress.Node,222 prog_node: std.Progress.Node,
234) link.File.FlushError!void {223) link.Error!void {
235 // The goal is to never use this because it's only needed if we need to224 // The goal is to never use this because it's only needed if we need to
236 // write to InternPool, but flush is too late to be writing to the225 // write to InternPool, but flush is too late to be writing to the
237 // InternPool.226 // InternPool.
src/link/Wasm.zig+19-19
...@@ -568,7 +568,7 @@ pub const SourceLocation = enum(u32) {...@@ -568,7 +568,7 @@ pub const SourceLocation = enum(u32) {
568 err_msg.notes[err.note_slot - 1].source_location = .{ .wasm = sl };568 err_msg.notes[err.note_slot - 1].source_location = .{ .wasm = sl };
569 }569 }
570570
571 pub fn fail(sl: SourceLocation, diags: *link.Diags, comptime format: []const u8, args: anytype) error{LinkFailure} {571 pub fn fail(sl: SourceLocation, diags: *link.Diags, comptime format: []const u8, args: anytype) error{AlreadyReported} {
572 return diags.failSourceLocation(.{ .wasm = sl }, format, args);572 return diags.failSourceLocation(.{ .wasm = sl }, format, args);
573 }573 }
574574
...@@ -3027,12 +3027,12 @@ fn openParseObjectReportingFailure(wasm: *Wasm, path: Path) void {...@@ -3027,12 +3027,12 @@ fn openParseObjectReportingFailure(wasm: *Wasm, path: Path) void {
3027 const diags = &comp.link_diags;3027 const diags = &comp.link_diags;
3028 const obj = link.openObject(io, path, false, false) catch |err| {3028 const obj = link.openObject(io, path, false, false) catch |err| {
3029 switch (diags.failParse(path, "failed to open object: {t}", .{err})) {3029 switch (diags.failParse(path, "failed to open object: {t}", .{err})) {
3030 error.LinkFailure => return,3030 error.AlreadyReported => return,
3031 }3031 }
3032 };3032 };
3033 wasm.parseObject(obj) catch |err| {3033 wasm.parseObject(obj) catch |err| {
3034 switch (diags.failParse(path, "failed to parse object: {t}", .{err})) {3034 switch (diags.failParse(path, "failed to parse object: {t}", .{err})) {
3035 error.LinkFailure => return,3035 error.AlreadyReported => return,
3036 }3036 }
3037 };3037 };
3038}3038}
...@@ -3336,12 +3336,12 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index...@@ -3336,12 +3336,12 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index
3336 }3336 }
3337}3337}
33383338
3339pub fn updateLineNumber(wasm: *Wasm, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {3339pub fn updateLineNumber(wasm: *Wasm, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) link.Error!void {
3340 const comp = wasm.base.comp;3340 const comp = wasm.base.comp;
3341 const diags = &comp.link_diags;3341 const diags = &comp.link_diags;
3342 if (wasm.dwarf) |*dw| {3342 if (wasm.dwarf) |*dw| {
3343 dw.updateLineNumber(pt.zcu, ti_id) catch |err| switch (err) {3343 dw.updateLineNumber(pt.zcu, ti_id) catch |err| switch (err) {
3344 error.Overflow, error.OutOfMemory => |e| return e,3344 error.OutOfMemory, error.Canceled, error.AlreadyReported => |e| return e,
3345 else => |e| return diags.fail("failed to update dwarf line numbers: {s}", .{@errorName(e)}),3345 else => |e| return diags.fail("failed to update dwarf line numbers: {s}", .{@errorName(e)}),
3346 };3346 };
3347 }3347 }
...@@ -3417,7 +3417,7 @@ pub fn loadInput(wasm: *Wasm, input: link.Input) !void {...@@ -3417,7 +3417,7 @@ pub fn loadInput(wasm: *Wasm, input: link.Input) !void {
3417 }3417 }
3418}3418}
34193419
3420pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!void {3420pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void {
3421 const tracy = trace(@src());3421 const tracy = trace(@src());
3422 defer tracy.end();3422 defer tracy.end();
34233423
...@@ -3526,7 +3526,7 @@ pub fn markFunctionImport(...@@ -3526,7 +3526,7 @@ pub fn markFunctionImport(
3526 name: String,3526 name: String,
3527 import: *FunctionImport,3527 import: *FunctionImport,
3528 func_index: FunctionImport.Index,3528 func_index: FunctionImport.Index,
3529) link.File.FlushError!void {3529) link.Error!void {
3530 // import.flags.alive might be already true from a previous update. In such3530 // import.flags.alive might be already true from a previous update. In such
3531 // case, we must still run the logic in this function, in case the item3531 // case, we must still run the logic in this function, in case the item
3532 // being marked was reverted by the `flush` logic that resets the hash3532 // being marked was reverted by the `flush` logic that resets the hash
...@@ -3557,7 +3557,7 @@ pub fn markFunctionImport(...@@ -3557,7 +3557,7 @@ pub fn markFunctionImport(
3557}3557}
35583558
3559/// Recursively mark alive everything referenced by the function.3559/// Recursively mark alive everything referenced by the function.
3560fn markFunction(wasm: *Wasm, i: ObjectFunctionIndex, override_export: bool) link.File.FlushError!void {3560fn markFunction(wasm: *Wasm, i: ObjectFunctionIndex, override_export: bool) link.Error!void {
3561 const comp = wasm.base.comp;3561 const comp = wasm.base.comp;
3562 const gpa = comp.gpa;3562 const gpa = comp.gpa;
3563 const gop = try wasm.functions.getOrPut(gpa, .fromObjectFunction(wasm, i));3563 const gop = try wasm.functions.getOrPut(gpa, .fromObjectFunction(wasm, i));
...@@ -3590,7 +3590,7 @@ fn markGlobalImport(...@@ -3590,7 +3590,7 @@ fn markGlobalImport(
3590 name: String,3590 name: String,
3591 import: *GlobalImport,3591 import: *GlobalImport,
3592 global_index: GlobalImport.Index,3592 global_index: GlobalImport.Index,
3593) link.File.FlushError!void {3593) link.Error!void {
3594 // import.flags.alive might be already true from a previous update. In such3594 // import.flags.alive might be already true from a previous update. In such
3595 // case, we must still run the logic in this function, in case the item3595 // case, we must still run the logic in this function, in case the item
3596 // being marked was reverted by the `flush` logic that resets the hash3596 // being marked was reverted by the `flush` logic that resets the hash
...@@ -3630,7 +3630,7 @@ fn markGlobalImport(...@@ -3630,7 +3630,7 @@ fn markGlobalImport(
3630 }3630 }
3631}3631}
36323632
3633fn markGlobal(wasm: *Wasm, i: ObjectGlobalIndex, override_export: bool) link.File.FlushError!void {3633fn markGlobal(wasm: *Wasm, i: ObjectGlobalIndex, override_export: bool) link.Error!void {
3634 const comp = wasm.base.comp;3634 const comp = wasm.base.comp;
3635 const gpa = comp.gpa;3635 const gpa = comp.gpa;
3636 const gop = try wasm.globals.getOrPut(gpa, .fromObjectGlobal(wasm, i));3636 const gop = try wasm.globals.getOrPut(gpa, .fromObjectGlobal(wasm, i));
...@@ -3653,7 +3653,7 @@ fn markTableImport(...@@ -3653,7 +3653,7 @@ fn markTableImport(
3653 name: String,3653 name: String,
3654 import: *TableImport,3654 import: *TableImport,
3655 table_index: TableImport.Index,3655 table_index: TableImport.Index,
3656) link.File.FlushError!void {3656) link.Error!void {
3657 if (import.flags.alive) return;3657 if (import.flags.alive) return;
3658 import.flags.alive = true;3658 import.flags.alive = true;
36593659
...@@ -3675,7 +3675,7 @@ fn markTableImport(...@@ -3675,7 +3675,7 @@ fn markTableImport(
3675 }3675 }
3676}3676}
36773677
3678fn markDataSegment(wasm: *Wasm, segment_index: ObjectDataSegment.Index) link.File.FlushError!void {3678fn markDataSegment(wasm: *Wasm, segment_index: ObjectDataSegment.Index) link.Error!void {
3679 const comp = wasm.base.comp;3679 const comp = wasm.base.comp;
3680 const segment = segment_index.ptr(wasm);3680 const segment = segment_index.ptr(wasm);
3681 if (segment.flags.alive) return;3681 if (segment.flags.alive) return;
...@@ -3693,7 +3693,7 @@ pub fn markDataImport(...@@ -3693,7 +3693,7 @@ pub fn markDataImport(
3693 name: String,3693 name: String,
3694 import: *ObjectDataImport,3694 import: *ObjectDataImport,
3695 data_index: ObjectDataImport.Index,3695 data_index: ObjectDataImport.Index,
3696) link.File.FlushError!void {3696) link.Error!void {
3697 if (import.flags.alive) return;3697 if (import.flags.alive) return;
3698 import.flags.alive = true;3698 import.flags.alive = true;
36993699
...@@ -3715,7 +3715,7 @@ pub fn markDataImport(...@@ -3715,7 +3715,7 @@ pub fn markDataImport(
3715 }3715 }
3716}3716}
37173717
3718fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.File.FlushError!void {3718fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.Error!void {
3719 const gpa = wasm.base.comp.gpa;3719 const gpa = wasm.base.comp.gpa;
3720 for (relocs.slice.tags(wasm), relocs.slice.pointees(wasm), relocs.slice.offsets(wasm)) |tag, pointee, offset| {3720 for (relocs.slice.tags(wasm), relocs.slice.pointees(wasm), relocs.slice.offsets(wasm)) |tag, pointee, offset| {
3721 if (offset >= relocs.end) break;3721 if (offset >= relocs.end) break;
...@@ -3812,7 +3812,7 @@ fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.Fil...@@ -3812,7 +3812,7 @@ fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.Fil
3812 }3812 }
3813}3813}
38143814
3815fn markTable(wasm: *Wasm, i: ObjectTableIndex) link.File.FlushError!void {3815fn markTable(wasm: *Wasm, i: ObjectTableIndex) link.Error!void {
3816 try wasm.tables.put(wasm.base.comp.gpa, .fromObjectTable(i), {});3816 try wasm.tables.put(wasm.base.comp.gpa, .fromObjectTable(i), {});
3817}3817}
38183818
...@@ -3821,7 +3821,7 @@ pub fn flush(...@@ -3821,7 +3821,7 @@ pub fn flush(
3821 arena: Allocator,3821 arena: Allocator,
3822 tid: Zcu.PerThread.Id,3822 tid: Zcu.PerThread.Id,
3823 prog_node: std.Progress.Node,3823 prog_node: std.Progress.Node,
3824) link.File.FlushError!void {3824) link.Error!void {
3825 // The goal is to never use this because it's only needed if we need to3825 // The goal is to never use this because it's only needed if we need to
3826 // write to InternPool, but flush is too late to be writing to the3826 // write to InternPool, but flush is too late to be writing to the
3827 // InternPool.3827 // InternPool.
...@@ -3864,7 +3864,7 @@ pub fn flush(...@@ -3864,7 +3864,7 @@ pub fn flush(
3864 try wasm.flush_buffer.data_imports.reinit(gpa, wasm.data_imports.keys(), wasm.data_imports.values());3864 try wasm.flush_buffer.data_imports.reinit(gpa, wasm.data_imports.keys(), wasm.data_imports.values());
38653865
3866 return wasm.flush_buffer.finish(wasm) catch |err| switch (err) {3866 return wasm.flush_buffer.finish(wasm) catch |err| switch (err) {
3867 error.OutOfMemory, error.LinkFailure => |e| return e,3867 error.OutOfMemory, error.AlreadyReported => |e| return e,
3868 else => |e| return diags.fail("failed to flush wasm: {s}", .{@errorName(e)}),3868 else => |e| return diags.fail("failed to flush wasm: {s}", .{@errorName(e)}),
3869 };3869 };
3870}3870}
...@@ -4275,7 +4275,7 @@ fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !Zcu...@@ -4275,7 +4275,7 @@ fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !Zcu
4275 {4275 {
4276 var aw: std.Io.Writer.Allocating = .fromArrayList(wasm.base.comp.gpa, &wasm.string_bytes);4276 var aw: std.Io.Writer.Allocating = .fromArrayList(wasm.base.comp.gpa, &wasm.string_bytes);
4277 defer wasm.string_bytes = aw.toArrayList();4277 defer wasm.string_bytes = aw.toArrayList();
4278 codegen.generateSymbol(&wasm.base, pt, .unneeded, .fromInterned(ip_index), &aw.writer, .none) catch |err| switch (err) {4278 codegen.generateSymbol(&wasm.base, pt, .fromInterned(ip_index), &aw.writer, .none) catch |err| switch (err) {
4279 error.WriteFailed => return error.OutOfMemory,4279 error.WriteFailed => return error.OutOfMemory,
4280 else => |e| return e,4280 else => |e| return e,
4281 };4281 };
...@@ -4349,7 +4349,7 @@ fn resolveFunctionSynthetic(...@@ -4349,7 +4349,7 @@ fn resolveFunctionSynthetic(
4349 res: FunctionImport.Resolution,4349 res: FunctionImport.Resolution,
4350 params: []const std.wasm.Valtype,4350 params: []const std.wasm.Valtype,
4351 returns: []const std.wasm.Valtype,4351 returns: []const std.wasm.Valtype,
4352) link.File.FlushError!void {4352) link.Error!void {
4353 import.resolution = res;4353 import.resolution = res;
4354 wasm.functions.putAssumeCapacity(res, {});4354 wasm.functions.putAssumeCapacity(res, {});
4355 // This is not only used for type-checking but also ensures the function4355 // This is not only used for type-checking but also ensures the function
src/link/Wasm/Flush.zig+3-3
...@@ -274,7 +274,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -274,7 +274,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
274 }274 }
275 }275 }
276276
277 if (diags.hasErrors()) return error.LinkFailure;277 if (diags.hasErrors()) return error.AlreadyReported;
278278
279 // Merge indirect function tables.279 // Merge indirect function tables.
280 try f.indirect_function_table.ensureUnusedCapacity(gpa, wasm.zcu_indirect_function_set.entries.len +280 try f.indirect_function_table.ensureUnusedCapacity(gpa, wasm.zcu_indirect_function_set.entries.len +
...@@ -513,7 +513,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -513,7 +513,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
513 if (initial_memory > std.math.maxInt(u32)) {513 if (initial_memory > std.math.maxInt(u32)) {
514 diags.addError("initial memory value {d} exceeds 32-bit address space", .{initial_memory});514 diags.addError("initial memory value {d} exceeds 32-bit address space", .{initial_memory});
515 }515 }
516 if (diags.hasErrors()) return error.LinkFailure;516 if (diags.hasErrors()) return error.AlreadyReported;
517 memory_ptr = initial_memory;517 memory_ptr = initial_memory;
518 } else {518 } else {
519 memory_ptr = mem.alignForward(u64, memory_ptr, std.wasm.page_size);519 memory_ptr = mem.alignForward(u64, memory_ptr, std.wasm.page_size);
...@@ -535,7 +535,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -535,7 +535,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
535 if (max_memory > std.math.maxInt(u32)) {535 if (max_memory > std.math.maxInt(u32)) {
536 diags.addError("maximum memory value {d} exceeds 32-bit address space", .{max_memory});536 diags.addError("maximum memory value {d} exceeds 32-bit address space", .{max_memory});
537 }537 }
538 if (diags.hasErrors()) return error.LinkFailure;538 if (diags.hasErrors()) return error.AlreadyReported;
539 wasm.memories.limits.max = @intCast(max_memory / page_size);539 wasm.memories.limits.max = @intCast(max_memory / page_size);
540 wasm.memories.limits.flags.has_max = true;540 wasm.memories.limits.flags.has_max = true;
541 if (shared_memory) wasm.memories.limits.flags.is_shared = true;541 if (shared_memory) wasm.memories.limits.flags.is_shared = true;
src/link/Wasm/Object.zig+1-1
...@@ -1431,7 +1431,7 @@ fn parseFeatures(...@@ -1431,7 +1431,7 @@ fn parseFeatures(
1431 bytes: []const u8,1431 bytes: []const u8,
1432 start_pos: usize,1432 start_pos: usize,
1433 path: Path,1433 path: Path,
1434) error{ OutOfMemory, LinkFailure }!struct { Wasm.Feature.Set, usize } {1434) error{ OutOfMemory, AlreadyReported }!struct { Wasm.Feature.Set, usize } {
1435 const gpa = wasm.base.comp.gpa;1435 const gpa = wasm.base.comp.gpa;
1436 const diags = &wasm.base.comp.link_diags;1436 const diags = &wasm.base.comp.link_diags;
1437 const features_len, var pos = readLeb(u32, bytes, start_pos);1437 const features_len, var pos = readLeb(u32, bytes, start_pos);
src/register_manager.zig+1-1
...@@ -14,7 +14,7 @@ const link = @import("link.zig");...@@ -14,7 +14,7 @@ const link = @import("link.zig");
1414
15const log = std.log.scoped(.register_manager);15const log = std.log.scoped(.register_manager);
1616
17pub const AllocationError = @import("codegen.zig").CodeGenError || error{OutOfRegisters};17pub const AllocationError = @import("codegen.zig").Error || error{OutOfRegisters};
1818
19pub fn RegisterManager(19pub fn RegisterManager(
20 comptime Function: type,20 comptime Function: type,