commit 8fe1ec0cc9cfd0f3cf85b97889b4b9735e906926 (tree)
parent 748e7c5e39fcba3ed6b2b6e4cc4c01e1d442acbe
Author: Matthew Lugg <mlugg@mlugg.co.uk>
Date: Sun, 31 May 2026 06:13:47 +0100
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...)
Diffstat:
42 files changed, 973 insertions(+), 1126 deletions(-)
diff --git a/src/Compilation.zig b/src/Compilation.zig
@@ -3376,7 +3376,7 @@ fn flush(comp: *Compilation, arena: Allocator, tid: Zcu.PerThread.Id) (Io.Cancel
.fuzz = comp.config.any_fuzz,
.lto = comp.config.lto,
}) catch |err| switch (err) {
- error.LinkFailure => {}, // Already reported.
+ error.AlreadyReported => {},
error.OutOfMemory => |e| return e,
};
}
@@ -3390,7 +3390,7 @@ fn flush(comp: *Compilation, arena: Allocator, tid: Zcu.PerThread.Id) (Io.Cancel
};
// This is needed before reading the error flags.
lf.flush(arena, tid, comp.link_prog_node) catch |err| switch (err) {
- error.LinkFailure => {}, // Already reported.
+ error.AlreadyReported => {},
error.OutOfMemory, error.Canceled => |e| return e,
};
}
@@ -5249,7 +5249,7 @@ fn workerUpdateCObject(
progress_node: std.Progress.Node,
) void {
comp.updateCObject(c_object, progress_node) catch |err| switch (err) {
- error.AnalysisFail => return,
+ error.AlreadyReported => return,
else => {
comp.reportRetryableCObjectError(c_object, err) catch |oom| switch (oom) {
// Swallowing this error is OK because it's implied to be OOM when
@@ -5266,7 +5266,7 @@ fn workerUpdateWin32Resource(
progress_node: std.Progress.Node,
) void {
comp.updateWin32Resource(win32_resource, progress_node) catch |err| switch (err) {
- error.AnalysisFail => return,
+ error.AlreadyReported => return,
else => {
comp.reportRetryableWin32ResourceError(win32_resource, err) catch |oom| switch (oom) {
// 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
c_object.status = .failure_retryable;
switch (comp.failCObj(c_object, "{t}", .{err})) {
- error.AnalysisFail => return,
+ error.AlreadyReported => return,
else => |e| return e,
}
}
@@ -6852,7 +6852,7 @@ fn failCObj(
c_object: *CObject,
comptime format: []const u8,
args: anytype,
-) error{ OutOfMemory, AnalysisFail } {
+) error{ OutOfMemory, AlreadyReported } {
@branchHint(.cold);
const diag_bundle = blk: {
const diag_bundle = try comp.gpa.create(CObject.Diag.Bundle);
@@ -6876,7 +6876,7 @@ fn failCObjWithOwnedDiagBundle(
comp: *Compilation,
c_object: *CObject,
diag_bundle: *CObject.Diag.Bundle,
-) error{ OutOfMemory, AnalysisFail } {
+) error{ OutOfMemory, AlreadyReported } {
@branchHint(.cold);
assert(diag_bundle.diags.len > 0);
{
@@ -6890,10 +6890,10 @@ fn failCObjWithOwnedDiagBundle(
comp.failed_c_objects.putAssumeCapacityNoClobber(c_object, diag_bundle);
}
c_object.status = .failure;
- return error.AnalysisFail;
+ return error.AlreadyReported;
}
-fn failWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, comptime format: []const u8, args: anytype) error{ OutOfMemory, AnalysisFail } {
+fn failWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, comptime format: []const u8, args: anytype) error{ OutOfMemory, AlreadyReported } {
@branchHint(.cold);
var bundle: ErrorBundle.Wip = undefined;
try bundle.init(comp.gpa);
@@ -6920,7 +6920,7 @@ fn failWin32ResourceWithOwnedBundle(
comp: *Compilation,
win32_resource: *Win32Resource,
err_bundle: ErrorBundle,
-) error{ OutOfMemory, AnalysisFail } {
+) error{ OutOfMemory, AlreadyReported } {
@branchHint(.cold);
{
const io = comp.io;
@@ -6929,7 +6929,7 @@ fn failWin32ResourceWithOwnedBundle(
try comp.failed_win32_resources.putNoClobber(comp.gpa, win32_resource, err_bundle);
}
win32_resource.status = .failure;
- return error.AnalysisFail;
+ return error.AlreadyReported;
}
pub const FileExt = enum {
diff --git a/src/Zcu.zig b/src/Zcu.zig
@@ -3912,12 +3912,12 @@ pub fn getTarget(zcu: *const Zcu) *const Target {
pub fn handleUpdateExports(
zcu: *Zcu,
export_indices: []const Export.Index,
- result: link.File.UpdateExportsError!void,
-) Allocator.Error!void {
+ result: link.Error!void,
+) (Allocator.Error || Io.Cancelable)!void {
const gpa = zcu.gpa;
result catch |err| switch (err) {
- error.OutOfMemory => |e| return e,
- error.AnalysisFail => {
+ else => |e| return e,
+ error.AlreadyReported => {
const export_idx = export_indices[0];
const new_export = export_idx.ptr(zcu);
new_export.status = .failed_retryable;
@@ -4688,7 +4688,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)
pub const CodegenFailError = error{
/// Indicates the error message has been already stored at `Zcu.failed_codegen`.
- CodegenFail,
+ AlreadyReported,
OutOfMemory,
};
@@ -4713,16 +4713,7 @@ pub fn codegenFailMsg(zcu: *Zcu, nav_index: InternPool.Nav.Index, msg: *ErrorMsg
errdefer msg.deinit(gpa);
try zcu.failed_codegen.putNoClobber(gpa, nav_index, msg);
}
- return error.CodegenFail;
-}
-
-/// Asserts that `zcu.failed_codegen` contains the key `nav`, with the necessary lock held.
-pub fn assertCodegenFailed(zcu: *Zcu, nav: InternPool.Nav.Index) void {
- const comp = zcu.comp;
- const io = comp.io;
- comp.mutex.lockUncancelable(io);
- defer comp.mutex.unlock(io);
- assert(zcu.failed_codegen.contains(nav));
+ return error.AlreadyReported;
}
pub fn codegenFailType(
@@ -4735,7 +4726,7 @@ pub fn codegenFailType(
try zcu.failed_types.ensureUnusedCapacity(gpa, 1);
const msg = try Zcu.ErrorMsg.create(gpa, zcu.typeSrcLoc(ty_index), format, args);
zcu.failed_types.putAssumeCapacityNoClobber(ty_index, msg);
- return error.CodegenFail;
+ return error.AlreadyReported;
}
pub 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)
try zcu.failed_types.ensureUnusedCapacity(gpa, 1);
}
zcu.failed_types.putAssumeCapacityNoClobber(ty_index, msg);
- return error.CodegenFail;
+ return error.AlreadyReported;
}
/// Asserts that `zcu.multi_module_err != null`.
diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig
@@ -3700,7 +3700,7 @@ fn processExportsInner(
exported: Zcu.Exported,
export_indices: []const Zcu.Export.Index,
skip_linker_work: bool,
-) error{OutOfMemory}!void {
+) error{ OutOfMemory, Canceled }!void {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const ip = &zcu.intern_pool;
@@ -4533,7 +4533,7 @@ pub fn runCodegen(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) Ru
return codegen_result catch |err| {
switch (err) {
error.OutOfMemory => comp.setAllocFailure(),
- error.CodegenFail => zcu.assertCodegenFailed(zcu.funcInfo(func_index).owner_nav),
+ error.AlreadyReported => {},
error.NoLinkFile => assert(comp.bin_file == null),
error.BackendDoesNotProduceMir => switch (target_util.zigBackend(
&zcu.root_mod.resolved_target.result,
@@ -4552,7 +4552,7 @@ pub fn runCodegen(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) Ru
fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) error{
OutOfMemory,
Canceled,
- CodegenFail,
+ AlreadyReported,
NoLinkFile,
BackendDoesNotProduceMir,
}!codegen.AnyMir {
@@ -4628,19 +4628,12 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e
switch (err) {
error.OutOfMemory => comp.link_diags.setAllocFailure(),
}
- return error.CodegenFail;
+ return error.AlreadyReported;
};
return error.BackendDoesNotProduceMir;
}
- return codegen.generateFunction(lf, pt, zcu.navSrcLoc(nav), func_index, air, &liveness) catch |err| switch (err) {
- error.OutOfMemory,
- error.CodegenFail,
- => |e| return e,
- error.Overflow,
- error.RelocationNotByteAligned,
- => return zcu.codegenFail(nav, "unable to codegen: {s}", .{@errorName(err)}),
- };
+ return codegen.generateFunction(lf, pt, func_index, air, &liveness);
}
fn printVerboseAir(
diff --git a/src/codegen.zig b/src/codegen.zig
@@ -24,10 +24,7 @@ const dev = @import("dev.zig");
pub const aarch64 = @import("codegen/aarch64.zig");
-pub const CodeGenError = GenerateSymbolError || error{
- /// Indicates the error is already stored in Zcu `failed_codegen`.
- CodegenFail,
-};
+pub const Error = link.Error;
fn devFeatureForBackend(backend: std.lang.CompilerBackend) dev.Feature {
return switch (backend) {
@@ -141,11 +138,10 @@ pub const AnyMir = union {
pub fn generateFunction(
lf: *link.File,
pt: Zcu.PerThread,
- src_loc: Zcu.LazySrcLoc,
func_index: InternPool.Index,
air: *const Air,
liveness: *const ?Air.Liveness,
-) CodeGenError!AnyMir {
+) Error!AnyMir {
const zcu = pt.zcu;
const func = zcu.funcInfo(func_index);
const target = &zcu.navFileScope(func.owner_nav).mod.?.resolved_target.result;
@@ -160,7 +156,7 @@ pub fn generateFunction(
=> |backend| {
dev.check(devFeatureForBackend(backend));
const CodeGen = importBackend(backend);
- const mir = try CodeGen.generate(lf, pt, src_loc, func_index, air, liveness);
+ const mir = try CodeGen.generate(lf, pt, func_index, air, liveness);
return @unionInit(AnyMir, AnyMir.tag(backend), mir);
},
}
@@ -176,13 +172,12 @@ pub fn generateFunction(
pub fn emitFunction(
lf: *link.File,
pt: Zcu.PerThread,
- src_loc: Zcu.LazySrcLoc,
func_index: InternPool.Index,
atom_id: link.File.AtomId,
any_mir: *const AnyMir,
w: *std.Io.Writer,
debug_output: link.File.DebugInfoOutput,
-) (CodeGenError || std.Io.Writer.Error)!void {
+) (Error || std.Io.Writer.Error)!void {
const zcu = pt.zcu;
const func = zcu.funcInfo(func_index);
const target = &zcu.navFileScope(func.owner_nav).mod.?.resolved_target.result;
@@ -201,7 +196,7 @@ pub fn emitFunction(
=> |backend| {
dev.check(devFeatureForBackend(backend));
const mir = &@field(any_mir, AnyMir.tag(backend));
- return mir.emit(lf, pt, src_loc, func_index, atom_id, w, debug_output);
+ return mir.emit(lf, pt, func_index, atom_id, w, debug_output);
},
}
}
@@ -209,12 +204,11 @@ pub fn emitFunction(
pub fn generateLazyFunction(
lf: *link.File,
pt: Zcu.PerThread,
- src_loc: Zcu.LazySrcLoc,
lazy_sym: link.File.LazySymbol,
atom_id: link.File.AtomId,
w: *std.Io.Writer,
debug_output: link.File.DebugInfoOutput,
-) (CodeGenError || std.Io.Writer.Error)!void {
+) (Error || std.Io.Writer.Error)!void {
const zcu = pt.zcu;
const target = if (Type.fromInterned(lazy_sym.ty).typeDeclInstAllowGeneratedTag(zcu)) |inst_index|
&zcu.fileByIndex(inst_index.resolveFile(&zcu.intern_pool)).mod.?.resolved_target.result
@@ -224,7 +218,7 @@ pub fn generateLazyFunction(
else => unreachable,
inline .stage2_riscv64, .stage2_x86_64 => |backend| {
dev.check(devFeatureForBackend(backend));
- return importBackend(backend).generateLazy(lf, pt, src_loc, lazy_sym, atom_id, w, debug_output);
+ return importBackend(backend).generateLazy(lf, pt, lazy_sym, atom_id, w, debug_output);
},
}
}
@@ -232,14 +226,13 @@ pub fn generateLazyFunction(
pub fn generateLazySymbol(
bin_file: *link.File,
pt: Zcu.PerThread,
- src_loc: Zcu.LazySrcLoc,
lazy_sym: link.File.LazySymbol,
// TODO don't use an "out" parameter like this; put it in the result instead
alignment: *Alignment,
w: *std.Io.Writer,
debug_output: link.File.DebugInfoOutput,
reloc_parent: link.File.RelocInfo.Parent,
-) (CodeGenError || std.Io.Writer.Error)!void {
+) (Error || std.Io.Writer.Error)!void {
const tracy = trace(@src());
defer tracy.end();
tracy.addTextFmt("{t}, {f}", .{ lazy_sym.kind, Type.fromInterned(lazy_sym.ty).fmt(pt) });
@@ -257,7 +250,7 @@ pub fn generateLazySymbol(
if (lazy_sym.kind == .code) {
alignment.* = target_util.defaultFunctionAlignment(target);
- return generateLazyFunction(bin_file, pt, src_loc, lazy_sym, reloc_parent.atom_index, w, debug_output);
+ return generateLazyFunction(bin_file, pt, lazy_sym, reloc_parent.atom_index, w, debug_output);
}
if (lazy_sym.ty == .anyerror_type) {
@@ -295,22 +288,13 @@ pub fn generateLazySymbol(
}
}
-pub const GenerateSymbolError = error{
- OutOfMemory,
- /// Compiler was asked to operate on a number larger than supported.
- Overflow,
- /// Compiler was asked to produce a non-byte-aligned relocation.
- RelocationNotByteAligned,
-};
-
pub fn generateSymbol(
bin_file: *link.File,
pt: Zcu.PerThread,
- src_loc: Zcu.LazySrcLoc,
val: Value,
w: *std.Io.Writer,
reloc_parent: link.File.RelocInfo.Parent,
-) (GenerateSymbolError || std.Io.Writer.Error)!void {
+) (Error || std.Io.Writer.Error)!void {
const tracy = trace(@src());
defer tracy.end();
@@ -323,8 +307,11 @@ pub fn generateSymbol(
log.debug("generateSymbol: val = {f}", .{val.fmtValue(pt)});
+ const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse {
+ return zcu.comp.link_diags.fail("failed to generate symbol: type size overflow", .{});
+ };
+
if (val.isUndef(zcu)) {
- const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;
try w.splatByteAll(0xaa, abi_size);
return;
}
@@ -364,7 +351,6 @@ pub fn generateSymbol(
.enum_literal,
=> unreachable, // non-runtime values
.int => {
- const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;
var space: Value.BigIntSpace = undefined;
const int_val = val.toBigInt(&space, zcu);
int_val.writeTwosComplement(try w.writableSlice(abi_size), endian);
@@ -397,13 +383,13 @@ pub fn generateSymbol(
// emit payload part of the error union
{
const begin = w.end;
- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(switch (error_union.val) {
+ try generateSymbol(bin_file, pt, Value.fromInterned(switch (error_union.val) {
.err_name => try pt.intern(.{ .undef = payload_ty.toIntern() }),
.payload => |payload| payload,
}), w, reloc_parent);
const unpadded_end = w.end - begin;
const padded_end = abi_align.forward(unpadded_end);
- const padding = math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow;
+ const padding: usize = @intCast(padded_end - unpadded_end);
if (padding > 0) {
try w.splatByteAll(0, padding);
@@ -416,7 +402,7 @@ pub fn generateSymbol(
try w.writeInt(u16, err_val, endian);
const unpadded_end = w.end - begin;
const padded_end = abi_align.forward(unpadded_end);
- const padding = math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow;
+ const padding: usize = @intCast(padded_end - unpadded_end);
if (padding > 0) {
try w.splatByteAll(0, padding);
@@ -425,7 +411,7 @@ pub fn generateSymbol(
},
.enum_tag => |enum_tag| {
const int_tag_ty = ty.intTagType(zcu);
- try generateSymbol(bin_file, pt, src_loc, try pt.getCoerced(Value.fromInterned(enum_tag.int), int_tag_ty), w, reloc_parent);
+ try generateSymbol(bin_file, pt, try pt.getCoerced(Value.fromInterned(enum_tag.int), int_tag_ty), w, reloc_parent);
},
.float => |float| storage: switch (float.storage) {
.f16 => |f16_val| try w.writeInt(u16, @bitCast(f16_val), endian),
@@ -433,7 +419,6 @@ pub fn generateSymbol(
.f64 => |f64_val| try w.writeInt(u64, @bitCast(f64_val), endian),
.f80 => |f80_val| {
try w.writeInt(u80, @bitCast(f80_val), endian);
- const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;
try w.splatByteAll(0, abi_size - 10);
},
.f128 => |f128_val| switch (Type.fromInterned(float.ty).floatBits(target)) {
@@ -444,29 +429,28 @@ pub fn generateSymbol(
128 => try w.writeInt(u128, @bitCast(f128_val), endian),
},
},
- .ptr => try lowerPtr(bin_file, pt, src_loc, val.toIntern(), w, reloc_parent, 0),
+ .ptr => try lowerPtr(bin_file, pt, val.toIntern(), w, reloc_parent, 0),
.slice => |slice| {
- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(slice.ptr), w, reloc_parent);
- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(slice.len), w, reloc_parent);
+ try generateSymbol(bin_file, pt, Value.fromInterned(slice.ptr), w, reloc_parent);
+ try generateSymbol(bin_file, pt, Value.fromInterned(slice.len), w, reloc_parent);
},
.opt => {
const payload_type = ty.optionalChild(zcu);
const payload_val = val.optionalValue(zcu);
- const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;
if (ty.optionalReprIsPayload(zcu)) {
if (payload_val) |value| {
- try generateSymbol(bin_file, pt, src_loc, value, w, reloc_parent);
+ try generateSymbol(bin_file, pt, value, w, reloc_parent);
} else {
try w.splatByteAll(0, abi_size);
}
} else {
- const padding = abi_size - (math.cast(usize, payload_type.abiSize(zcu)) orelse return error.Overflow) - 1;
+ const padding = abi_size - @as(usize, @intCast(payload_type.abiSize(zcu))) - 1;
if (payload_type.hasRuntimeBits(zcu)) {
const value = payload_val orelse Value.fromInterned(try pt.intern(.{
.undef = payload_type.toIntern(),
}));
- try generateSymbol(bin_file, pt, src_loc, value, w, reloc_parent);
+ try generateSymbol(bin_file, pt, value, w, reloc_parent);
}
try w.writeByte(@intFromBool(payload_val != null));
try w.splatByteAll(0, padding);
@@ -478,7 +462,7 @@ pub fn generateSymbol(
.elems, .repeated_elem => {
var index: u64 = 0;
while (index < array_type.lenIncludingSentinel()) : (index += 1) {
- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(switch (aggregate.storage) {
+ try generateSymbol(bin_file, pt, Value.fromInterned(switch (aggregate.storage) {
.bytes => unreachable,
.elems => |elems| elems[@intCast(index)],
.repeated_elem => |elem| if (index < array_type.len)
@@ -490,7 +474,6 @@ pub fn generateSymbol(
},
},
.vector_type => |vector_type| {
- const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;
const vector_bool_bitpacked = switch (zcu.comp.getZigBackend()) {
.stage2_wasm => false,
else => true,
@@ -499,7 +482,9 @@ pub fn generateSymbol(
const bytes = try w.writableSlice(abi_size);
@memset(bytes, 0xaa);
var index: usize = 0;
- const len = math.cast(usize, vector_type.len) orelse return error.Overflow;
+ const len = math.cast(usize, vector_type.len) orelse {
+ return zcu.comp.link_diags.fail("failed to generate symbol: vector length overflow", .{});
+ };
while (index < len) : (index += 1) {
const bit_index = switch (endian) {
.big => len - 1 - index,
@@ -539,18 +524,16 @@ pub fn generateSymbol(
.elems, .repeated_elem => {
var index: u64 = 0;
while (index < vector_type.len) : (index += 1) {
- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(switch (aggregate.storage) {
+ try generateSymbol(bin_file, pt, Value.fromInterned(switch (aggregate.storage) {
.bytes => unreachable,
- .elems => |elems| elems[math.cast(usize, index) orelse return error.Overflow],
+ .elems => |elems| elems[@intCast(index)],
.repeated_elem => |elem| elem,
}), w, reloc_parent);
}
},
}
- const padding = abi_size -
- (math.cast(usize, Type.fromInterned(vector_type.child).abiSize(zcu) * vector_type.len) orelse
- return error.Overflow);
+ const padding = abi_size - @as(usize, @intCast(Type.fromInterned(vector_type.child).abiSize(zcu) * vector_type.len));
if (padding > 0) try w.splatByteAll(0, padding);
}
},
@@ -560,10 +543,9 @@ pub fn generateSymbol(
if (field_val != .none) continue;
if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue;
- try w.splatByteAll(0, math.cast(usize, struct_begin +
- Type.fromInterned(field_ty).abiAlignment(zcu).forward(w.end - struct_begin) - w.end) orelse
- return error.Overflow);
- try generateSymbol(bin_file, pt, src_loc, .fromInterned(switch (aggregate.storage) {
+ try w.splatByteAll(0, @intCast(struct_begin +
+ Type.fromInterned(field_ty).abiAlignment(zcu).forward(w.end - struct_begin) - w.end));
+ try generateSymbol(bin_file, pt, .fromInterned(switch (aggregate.storage) {
.bytes => |bytes| try pt.intern(.{ .int = .{
.ty = field_ty,
.storage = .{ .u64 = bytes.at(field_index, ip) },
@@ -572,8 +554,7 @@ pub fn generateSymbol(
.repeated_elem => |elem| elem,
}), w, reloc_parent);
}
- try w.splatByteAll(0, math.cast(usize, struct_begin + ty.abiSize(zcu) - w.end) orelse
- return error.Overflow);
+ try w.splatByteAll(0, @intCast(struct_begin + ty.abiSize(zcu) - w.end));
},
.struct_type => {
const struct_type = ip.loadStructType(ty.toIntern());
@@ -598,20 +579,15 @@ pub fn generateSymbol(
.repeated_elem => |elem| elem,
};
- const padding = math.cast(
- usize,
- offsets[field_index] - (w.end - struct_begin),
- ) orelse return error.Overflow;
+ const padding: usize = @intCast(offsets[field_index] - (w.end - struct_begin));
if (padding > 0) try w.splatByteAll(0, padding);
- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), w, reloc_parent);
+ try generateSymbol(bin_file, pt, Value.fromInterned(field_val), w, reloc_parent);
}
assert(struct_type.alignment.check(struct_type.size));
- const padding = math.cast(usize, struct_type.size - (w.end - struct_begin)) orelse {
- return error.Overflow;
- };
+ const padding: usize = @intCast(struct_type.size - (w.end - struct_begin));
if (padding > 0) try w.splatByteAll(0, padding);
},
}
@@ -622,12 +598,12 @@ pub fn generateSymbol(
const layout = ty.unionGetLayout(zcu);
if (layout.payload_size == 0) {
- return generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), w, reloc_parent);
+ return generateSymbol(bin_file, pt, Value.fromInterned(un.tag), w, reloc_parent);
}
// Check if we should store the tag first.
if (layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)) {
- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), w, reloc_parent);
+ try generateSymbol(bin_file, pt, Value.fromInterned(un.tag), w, reloc_parent);
}
const union_obj = zcu.typeToUnion(ty).?;
@@ -635,28 +611,28 @@ pub fn generateSymbol(
const field_index = ty.unionTagFieldIndex(Value.fromInterned(un.tag), zcu).?;
const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
if (!field_ty.hasRuntimeBits(zcu)) {
- try w.splatByteAll(0xaa, math.cast(usize, layout.payload_size) orelse return error.Overflow);
+ try w.splatByteAll(0xaa, @intCast(layout.payload_size));
} else {
- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.val), w, reloc_parent);
+ try generateSymbol(bin_file, pt, Value.fromInterned(un.val), w, reloc_parent);
- const padding = math.cast(usize, layout.payload_size - field_ty.abiSize(zcu)) orelse return error.Overflow;
+ const padding: usize = @intCast(layout.payload_size - field_ty.abiSize(zcu));
if (padding > 0) {
try w.splatByteAll(0, padding);
}
}
} else {
- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.val), w, reloc_parent);
+ try generateSymbol(bin_file, pt, Value.fromInterned(un.val), w, reloc_parent);
}
if (layout.tag_size > 0 and layout.tag_align.compare(.lt, layout.payload_align)) {
- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), w, reloc_parent);
+ try generateSymbol(bin_file, pt, Value.fromInterned(un.tag), w, reloc_parent);
if (layout.padding > 0) {
try w.splatByteAll(0, layout.padding);
}
}
},
- .bitpack => |bitpack| try generateSymbol(bin_file, pt, src_loc, .fromInterned(bitpack.backing_int_val), w, reloc_parent),
+ .bitpack => |bitpack| try generateSymbol(bin_file, pt, .fromInterned(bitpack.backing_int_val), w, reloc_parent),
.memoized_call => unreachable,
}
}
@@ -664,23 +640,21 @@ pub fn generateSymbol(
fn lowerPtr(
bin_file: *link.File,
pt: Zcu.PerThread,
- src_loc: Zcu.LazySrcLoc,
ptr_val: InternPool.Index,
w: *std.Io.Writer,
reloc_parent: link.File.RelocInfo.Parent,
prev_offset: u64,
-) (GenerateSymbolError || std.Io.Writer.Error)!void {
+) (Error || std.Io.Writer.Error)!void {
const zcu = pt.zcu;
const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr;
const offset: u64 = prev_offset + ptr.byte_offset;
return switch (ptr.base_addr) {
.nav => |nav| try lowerNavRef(bin_file, pt, nav, w, reloc_parent, offset),
- .uav => |uav| try lowerUavRef(bin_file, pt, src_loc, uav, w, reloc_parent, offset),
- .int => try generateSymbol(bin_file, pt, src_loc, try pt.intValue(Type.usize, offset), w, reloc_parent),
+ .uav => |uav| try lowerUavRef(bin_file, pt, uav, w, reloc_parent, offset),
+ .int => try generateSymbol(bin_file, pt, try pt.intValue(Type.usize, offset), w, reloc_parent),
.eu_payload => |eu_ptr| try lowerPtr(
bin_file,
pt,
- src_loc,
eu_ptr,
w,
reloc_parent,
@@ -689,7 +663,7 @@ fn lowerPtr(
zcu,
),
),
- .opt_payload => |opt_ptr| try lowerPtr(bin_file, pt, src_loc, opt_ptr, w, reloc_parent, offset),
+ .opt_payload => |opt_ptr| try lowerPtr(bin_file, pt, opt_ptr, w, reloc_parent, offset),
.field => |field| {
const base_ptr = Value.fromInterned(field.base);
const base_ty = base_ptr.typeOf(zcu).childType(zcu);
@@ -708,13 +682,13 @@ fn lowerPtr(
},
else => unreachable,
};
- return lowerPtr(bin_file, pt, src_loc, field.base, w, reloc_parent, offset + field_off);
+ return lowerPtr(bin_file, pt, field.base, w, reloc_parent, offset + field_off);
},
.arr_elem => |arr_elem| {
const base_ptr_ty = Value.fromInterned(arr_elem.base).typeOf(zcu);
assert(base_ptr_ty.ptrSize(zcu) == .many);
const elem_size = base_ptr_ty.childType(zcu).abiSize(zcu);
- return lowerPtr(bin_file, pt, src_loc, arr_elem.base, w, reloc_parent, offset + elem_size * arr_elem.index);
+ return lowerPtr(bin_file, pt, arr_elem.base, w, reloc_parent, offset + elem_size * arr_elem.index);
},
.comptime_alloc => unreachable,
.comptime_field => unreachable,
@@ -724,12 +698,11 @@ fn lowerPtr(
fn lowerUavRef(
lf: *link.File,
pt: Zcu.PerThread,
- src_loc: Zcu.LazySrcLoc,
uav: InternPool.Key.Ptr.BaseAddr.Uav,
w: *std.Io.Writer,
reloc_parent: link.File.RelocInfo.Parent,
offset: u64,
-) (GenerateSymbolError || std.Io.Writer.Error)!void {
+) (Error || std.Io.Writer.Error)!void {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
const comp = lf.comp;
@@ -761,10 +734,7 @@ fn lowerUavRef(
}
const uav_align = Type.fromInterned(uav.orig_ty).ptrAlignment(zcu);
- switch (try lf.lowerUav(pt, uav_val, uav_align, src_loc)) {
- .sym_index => {},
- .fail => |em| std.debug.panic("TODO rework lowerUav. internal error: {s}", .{em.msg}),
- }
+ _ = try lf.lowerUav(pt, uav_val, uav_align);
const vaddr = lf.getUavVAddr(uav_val, .{
.parent = reloc_parent,
@@ -790,7 +760,7 @@ fn lowerNavRef(
w: *std.Io.Writer,
reloc_parent: link.File.RelocInfo.Parent,
offset: u64,
-) (GenerateSymbolError || std.Io.Writer.Error)!void {
+) (Error || std.Io.Writer.Error)!void {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const ip = &zcu.intern_pool;
@@ -859,15 +829,11 @@ fn lowerNavRef(
}
}
-pub const SymbolResult = union(enum) { sym_index: link.File.SymbolId, fail: *ErrorMsg };
-
pub fn genNavRef(
lf: *link.File,
pt: Zcu.PerThread,
- src_loc: Zcu.LazySrcLoc,
nav_index: InternPool.Nav.Index,
- target: *const std.Target,
-) CodeGenError!SymbolResult {
+) Error!link.File.SymbolId {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
const nav = ip.getNav(nav_index);
@@ -884,7 +850,7 @@ pub fn genNavRef(
.internal => {
const sym_index = try zo.getOrCreateMetadataForNav(zcu, nav_index);
if (is_threadlocal) zo.symbol(sym_index).flags.is_tls = true;
- return .{ .sym_index = @enumFromInt(sym_index) };
+ return @enumFromInt(sym_index);
},
.strong, .weak => {
const sym_index = try elf_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));
@@ -895,27 +861,19 @@ pub fn genNavRef(
.link_once => unreachable,
}
if (is_threadlocal) zo.symbol(sym_index).flags.is_tls = true;
- return .{ .sym_index = @enumFromInt(sym_index) };
+ return @enumFromInt(sym_index);
},
.link_once => unreachable,
}
} else if (lf.cast(.elf2)) |elf| {
- return .{ .sym_index = elf.navSymbol(nav_index) catch |err| switch (err) {
- error.OutOfMemory => |e| return e,
- else => |e| return .{ .fail = try ErrorMsg.create(
- zcu.gpa,
- src_loc,
- "linker failed to create a nav: {t}",
- .{e},
- ) },
- } };
+ return elf.navSymbol(nav_index);
} else if (lf.cast(.macho)) |macho_file| {
const zo = macho_file.getZigObject().?;
switch (linkage) {
.internal => {
const sym_index = try zo.getOrCreateMetadataForNav(macho_file, nav_index);
if (is_threadlocal) zo.symbols.items[sym_index].flags.tlv = true;
- return .{ .sym_index = @enumFromInt(sym_index) };
+ return @enumFromInt(sym_index);
},
.strong, .weak => {
const sym_index = try macho_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));
@@ -926,80 +884,67 @@ pub fn genNavRef(
.link_once => unreachable,
}
if (is_threadlocal) zo.symbols.items[sym_index].flags.tlv = true;
- return .{ .sym_index = @enumFromInt(sym_index) };
+ return @enumFromInt(sym_index);
},
.link_once => unreachable,
}
} else if (lf.cast(.coff2)) |coff| {
- return .{ .sym_index = @enumFromInt(@intFromEnum(try coff.navSymbol(zcu, nav_index))) };
+ return @enumFromInt(@intFromEnum(try coff.navSymbol(zcu, nav_index)));
} else {
- const msg = try ErrorMsg.create(zcu.gpa, src_loc, "TODO genNavRef for target {}", .{target});
- return .{ .fail = msg };
+ std.debug.panic("TODO genNavRef for '{t}'", .{lf.tag});
}
}
/// deprecated legacy type
-pub const GenResult = union(enum) {
- mcv: MCValue,
- fail: *ErrorMsg,
-
- const MCValue = union(enum) {
- none,
- undef,
- /// The bit-width of the immediate may be smaller than `u64`. For example, on 32-bit targets
- /// such as ARM, the immediate will never exceed 32-bits.
- immediate: u64,
- /// Decl with address deferred until the linker allocates everything in virtual memory.
- /// Payload is a symbol index.
- load_direct: link.File.SymbolId,
- /// Decl with address deferred until the linker allocates everything in virtual memory.
- /// Payload is a symbol index.
- lea_direct: link.File.SymbolId,
- /// Decl referenced via GOT with address deferred until the linker allocates
- /// everything in virtual memory.
- /// Payload is a symbol index.
- load_got: link.File.SymbolId,
- /// Direct by-address reference to memory location.
- memory: u64,
- /// Reference to memory location but deferred until linker allocated the Decl in memory.
- /// Traditionally, this corresponds to emitting a relocation in a relocatable object file.
- load_symbol: link.File.SymbolId,
- /// Reference to memory location but deferred until linker allocated the Decl in memory.
- /// Traditionally, this corresponds to emitting a relocation in a relocatable object file.
- lea_symbol: link.File.SymbolId,
- };
+pub const MCValue = union(enum) {
+ none,
+ undef,
+ /// The bit-width of the immediate may be smaller than `u64`. For example, on 32-bit targets
+ /// such as ARM, the immediate will never exceed 32-bits.
+ immediate: u64,
+ /// Decl with address deferred until the linker allocates everything in virtual memory.
+ /// Payload is a symbol index.
+ load_direct: link.File.SymbolId,
+ /// Decl with address deferred until the linker allocates everything in virtual memory.
+ /// Payload is a symbol index.
+ lea_direct: link.File.SymbolId,
+ /// Decl referenced via GOT with address deferred until the linker allocates
+ /// everything in virtual memory.
+ /// Payload is a symbol index.
+ load_got: link.File.SymbolId,
+ /// Direct by-address reference to memory location.
+ memory: u64,
+ /// Reference to memory location but deferred until linker allocated the Decl in memory.
+ /// Traditionally, this corresponds to emitting a relocation in a relocatable object file.
+ load_symbol: link.File.SymbolId,
+ /// Reference to memory location but deferred until linker allocated the Decl in memory.
+ /// Traditionally, this corresponds to emitting a relocation in a relocatable object file.
+ lea_symbol: link.File.SymbolId,
};
/// deprecated legacy code path
pub fn genTypedValue(
lf: *link.File,
pt: Zcu.PerThread,
- src_loc: Zcu.LazySrcLoc,
val: Value,
target: *const std.Target,
-) CodeGenError!GenResult {
+) Error!MCValue {
const res = try lowerValue(pt, val, target);
return switch (res) {
- .none => .{ .mcv = .none },
- .undef => .{ .mcv = .undef },
- .immediate => |imm| .{ .mcv = .{ .immediate = imm } },
- .lea_nav => |nav| switch (try genNavRef(lf, pt, src_loc, nav, target)) {
- .sym_index => |sym_index| .{ .mcv = .{ .lea_symbol = sym_index } },
- .fail => |em| .{ .fail = em },
- },
- .load_uav, .lea_uav => |uav| switch (try lf.lowerUav(
+ .none => .none,
+ .undef => .undef,
+ .immediate => |imm| .{ .immediate = imm },
+ .lea_nav => |nav| .{ .lea_symbol = try genNavRef(lf, pt, nav) },
+ .load_uav => |uav| .{ .load_symbol = try lf.lowerUav(
pt,
uav.val,
Type.fromInterned(uav.orig_ty).ptrAlignment(pt.zcu),
- src_loc,
- )) {
- .sym_index => |sym_index| .{ .mcv = switch (res) {
- else => unreachable,
- .load_uav => .{ .load_symbol = sym_index },
- .lea_uav => .{ .lea_symbol = sym_index },
- } },
- .fail => |em| .{ .fail = em },
- },
+ ) },
+ .lea_uav => |uav| .{ .lea_symbol = try lf.lowerUav(
+ pt,
+ uav.val,
+ Type.fromInterned(uav.orig_ty).ptrAlignment(pt.zcu),
+ ) },
};
}
diff --git a/src/codegen/aarch64.zig b/src/codegen/aarch64.zig
@@ -12,7 +12,6 @@ pub fn legalizeFeatures(_: *const std.Target) ?*Air.Legalize.Features {
pub fn generate(
_: *link.File,
pt: Zcu.PerThread,
- _: Zcu.LazySrcLoc,
func_index: InternPool.Index,
air: *const Air,
liveness: *const ?Air.Liveness,
diff --git a/src/codegen/aarch64/Mir.zig b/src/codegen/aarch64/Mir.zig
@@ -54,7 +54,6 @@ pub fn emit(
mir: Mir,
lf: *link.File,
pt: Zcu.PerThread,
- src_loc: Zcu.LazySrcLoc,
func_index: InternPool.Index,
atom_index: link.File.AtomId,
w: *std.Io.Writer,
@@ -94,16 +93,11 @@ pub fn emit(
lf,
zcu,
atom_index,
- switch (try @import("../../codegen.zig").genNavRef(
+ try @import("../../codegen.zig").genNavRef(
lf,
pt,
- src_loc,
nav_reloc.nav,
- &mod.resolved_target.result,
- )) {
- .sym_index => |sym_index| sym_index,
- .fail => |em| return zcu.codegenFailMsg(func.owner_nav, em),
- },
+ ),
mir.body[nav_reloc.reloc.label],
body_end - Instruction.size * (1 + nav_reloc.reloc.label),
nav_reloc.reloc.addend,
@@ -113,15 +107,11 @@ pub fn emit(
lf,
zcu,
atom_index,
- switch (try lf.lowerUav(
+ try lf.lowerUav(
pt,
uav_reloc.uav.val,
ZigType.fromInterned(uav_reloc.uav.orig_ty).ptrAlignment(zcu),
- src_loc,
- )) {
- .sym_index => |sym_index| sym_index,
- .fail => |em| return zcu.codegenFailMsg(func.owner_nav, em),
- },
+ ),
mir.body[uav_reloc.reloc.label],
body_end - Instruction.size * (1 + uav_reloc.reloc.label),
uav_reloc.reloc.addend,
diff --git a/src/codegen/aarch64/Select.zig b/src/codegen/aarch64/Select.zig
@@ -883,7 +883,7 @@ pub fn finishAnalysis(isel: *Select) !void {
}
}
-pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, CodegenFail }!void {
+pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, AlreadyReported }!void {
const zcu = isel.pt.zcu;
const ip = &zcu.intern_pool;
const gpa = zcu.gpa;
@@ -8001,7 +8001,7 @@ fn emitLiteral(isel: *Select, bytes: []const u8) !void {
}
}
-fn fail(isel: *Select, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {
+fn fail(isel: *Select, comptime format: []const u8, args: anytype) error{ OutOfMemory, AlreadyReported } {
@branchHint(.cold);
return isel.pt.zcu.codegenFail(isel.nav_index, format, args);
}
@@ -10595,7 +10595,7 @@ pub const Value = struct {
vi: Value.Index,
ra: Register.Alias,
- fn finish(mat: Value.Materialize, isel: *Select) error{ OutOfMemory, CodegenFail }!void {
+ fn finish(mat: Value.Materialize, isel: *Select) error{ OutOfMemory, AlreadyReported }!void {
const live_vi = isel.live_registers.getPtr(mat.ra);
assert(live_vi.* == .allocating);
var vi = mat.vi;
@@ -11636,7 +11636,7 @@ fn use(isel: *Select, air_ref: Air.Inst.Ref) !Value.Index {
return vi;
}
-fn fill(isel: *Select, dst_ra: Register.Alias) error{ OutOfMemory, CodegenFail }!bool {
+fn fill(isel: *Select, dst_ra: Register.Alias) error{ OutOfMemory, AlreadyReported }!bool {
switch (dst_ra) {
else => {},
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 }
return true;
}
-fn fillMemory(isel: *Select, dst_ra: Register.Alias) error{ OutOfMemory, CodegenFail }!bool {
+fn fillMemory(isel: *Select, dst_ra: Register.Alias) error{ OutOfMemory, AlreadyReported }!bool {
const dst_live_vi = isel.live_registers.getPtr(dst_ra);
const dst_vi = switch (dst_live_vi.*) {
_ => |dst_vi| dst_vi,
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
@@ -80,7 +80,7 @@ pub const Mir = struct {
}
};
-pub const Error = Writer.Error || Allocator.Error || error{AnalysisFail};
+pub const Error = Writer.Error || Allocator.Error || error{AlreadyReported};
pub const CType = @import("c/type.zig").CType;
@@ -637,7 +637,6 @@ pub const DeclGen = struct {
owner_nav: InternPool.Nav.Index.Optional,
is_naked_fn: bool,
expected_block: ?u32,
- error_msg: ?*Zcu.ErrorMsg,
ctype_deps: CType.Dependencies,
/// This map contains all the UAVs we saw generating this function.
/// `link.C` will merge them into its `uavs`/`aligned_uavs` fields.
@@ -648,10 +647,7 @@ pub const DeclGen = struct {
fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) Error {
@branchHint(.cold);
- const zcu = dg.pt.zcu;
- const src_loc = zcu.navSrcLoc(dg.owner_nav.unwrap().?);
- dg.error_msg = try Zcu.ErrorMsg.create(dg.gpa, src_loc, format, args);
- return error.AnalysisFail;
+ return dg.pt.zcu.codegenFail(dg.owner_nav.unwrap().?, format, args);
}
fn renderUav(
@@ -2184,15 +2180,13 @@ pub fn genLazyCallModifierFn(
pub fn generate(
lf: *link.File,
pt: Zcu.PerThread,
- src_loc: Zcu.LazySrcLoc,
func_index: InternPool.Index,
air: *const Air,
liveness: *const ?Air.Liveness,
-) @import("../codegen.zig").CodeGenError!Mir {
+) @import("../codegen.zig").Error!Mir {
const zcu = pt.zcu;
const gpa = zcu.gpa;
- _ = src_loc;
assert(lf.tag == .c);
const func = zcu.funcInfo(func_index);
@@ -2210,7 +2204,6 @@ pub fn generate(
.arena = arena.allocator(),
.pt = pt,
.mod = zcu.navFileScope(func.owner_nav).mod.?,
- .error_msg = null,
.owner_nav = func.owner_nav.toOptional(),
.is_naked_fn = Type.fromInterned(func.ty).fnCallingConvention(zcu) == .naked,
.expected_block = null,
@@ -2237,9 +2230,8 @@ pub fn generate(
defer code_header.deinit();
genFunc(&function, &fwd_decl.writer, &code_header.writer) catch |err| switch (err) {
- error.AnalysisFail => return zcu.codegenFailMsg(func.owner_nav, function.dg.error_msg.?),
error.WriteFailed => return error.OutOfMemory,
- error.OutOfMemory => |e| return e,
+ else => |e| return e,
};
var mir: Mir = .{
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
@@ -771,7 +771,7 @@ pub const Object = struct {
lto: std.zig.LtoMode,
};
- pub fn emit(o: *Object, pt: Zcu.PerThread, options: EmitOptions) error{ LinkFailure, OutOfMemory }!void {
+ pub fn emit(o: *Object, pt: Zcu.PerThread, options: EmitOptions) error{ AlreadyReported, OutOfMemory }!void {
const zcu = o.zcu;
const comp = zcu.comp;
const io = comp.io;
@@ -1705,7 +1705,7 @@ pub const Object = struct {
o: *Object,
exported: Zcu.Exported,
export_indices: []const Zcu.Export.Index,
- ) link.File.UpdateExportsError!void {
+ ) link.Error!void {
const zcu = o.zcu;
const ip = &zcu.intern_pool;
const ty: Type, const llvm_ptr: Builder.Constant = switch (exported) {
@@ -1735,7 +1735,7 @@ pub const Object = struct {
global_index: Builder.Global.Index,
ty: Type,
export_indices: []const Zcu.Export.Index,
- ) link.File.UpdateExportsError!void {
+ ) link.Error!void {
const zcu = o.zcu;
const comp = zcu.comp;
const ip = &zcu.intern_pool;
diff --git a/src/codegen/riscv64/CodeGen.zig b/src/codegen/riscv64/CodeGen.zig
@@ -30,8 +30,6 @@ const verbose_tracking_log = std.log.scoped(.verbose_tracking);
const wip_mir_log = std.log.scoped(.wip_mir);
const Alignment = InternPool.Alignment;
-const CodeGenError = codegen.CodeGenError;
-
const bits = @import("bits.zig");
const abi = @import("abi.zig");
const Lower = @import("Lower.zig");
@@ -49,7 +47,7 @@ const RegisterManager = abi.RegisterManager;
const RegisterLock = RegisterManager.RegisterLock;
const Instruction = encoding.Instruction;
-const InnerError = CodeGenError || error{OutOfRegisters};
+const InnerError = codegen.Error || error{OutOfRegisters};
pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
return comptime &.initMany(&.{
@@ -75,7 +73,6 @@ ret_mcv: InstTracking,
func_index: InternPool.Index,
fn_type: Type,
arg_index: usize,
-src_loc: Zcu.LazySrcLoc,
mir_instructions: std.MultiArrayList(Mir.Inst) = .{},
@@ -742,11 +739,10 @@ const CallView = enum(u1) {
pub fn generate(
bin_file: *link.File,
pt: Zcu.PerThread,
- src_loc: Zcu.LazySrcLoc,
func_index: InternPool.Index,
air: *const Air,
liveness: *const ?Air.Liveness,
-) CodeGenError!Mir {
+) codegen.Error!Mir {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const ip = &zcu.intern_pool;
@@ -777,7 +773,6 @@ pub fn generate(
.fn_type = fn_type,
.arg_index = 0,
.branch_stack = &branch_stack,
- .src_loc = src_loc,
.end_di_line = func.rbrace_line,
.end_di_column = func.rbrace_column,
.scope_generation = 0,
@@ -811,10 +806,7 @@ pub fn generate(
);
const fn_info = zcu.typeToFunc(fn_type).?;
- var call_info = function.resolveCallingConventionValues(fn_info, &.{}) catch |err| switch (err) {
- error.CodegenFail => |e| return e,
- else => |e| return e,
- };
+ var call_info = try function.resolveCallingConventionValues(fn_info, &.{});
defer call_info.deinit(&function);
@@ -841,7 +833,6 @@ pub fn generate(
}));
function.gen() catch |err| switch (err) {
- error.CodegenFail => |e| return e,
error.OutOfRegisters => return function.fail("ran out of registers (Zig compiler bug)", .{}),
else => |e| return e,
};
@@ -857,12 +848,11 @@ pub fn generate(
pub fn generateLazy(
bin_file: *link.File,
pt: Zcu.PerThread,
- src_loc: Zcu.LazySrcLoc,
lazy_sym: link.File.LazySymbol,
atom_index: link.File.AtomId,
w: *std.Io.Writer,
debug_output: link.File.DebugInfoOutput,
-) (CodeGenError || std.Io.Writer.Error)!void {
+) (codegen.Error || std.Io.Writer.Error)!void {
_ = atom_index;
const comp = bin_file.comp;
const gpa = comp.gpa;
@@ -883,7 +873,6 @@ pub fn generateLazy(
.fn_type = undefined,
.arg_index = 0,
.branch_stack = undefined,
- .src_loc = src_loc,
.end_di_line = undefined,
.end_di_column = undefined,
.scope_generation = 0,
@@ -893,7 +882,6 @@ pub fn generateLazy(
defer function.mir_instructions.deinit(gpa);
function.genLazy(lazy_sym) catch |err| switch (err) {
- error.CodegenFail => |e| return e,
error.OutOfRegisters => return function.fail("ran out of registers (Zig compiler bug)", .{}),
else => |e| return e,
};
@@ -910,7 +898,7 @@ pub fn generateLazy(
.allocator = gpa,
.mir = mir,
.cc = .auto,
- .src_loc = src_loc,
+ .src_loc = Type.fromInterned(lazy_sym.ty).srcLocOrNull(pt.zcu) orelse .unneeded,
.output_mode = comp.config.output_mode,
.link_mode = comp.config.link_mode,
.pic = mod.pic,
@@ -946,7 +934,10 @@ fn formatWipMir(data: FormatWipMirData, writer: *std.Io.Writer) std.Io.Writer.Er
.frame_locs = data.func.frame_locs.slice(),
},
.cc = .auto,
- .src_loc = data.func.src_loc,
+ .src_loc = switch (data.func.owner) {
+ .nav_index => |nav| pt.zcu.navSrcLoc(nav),
+ .lazy_sym => |lazy_sym| Type.fromInterned(lazy_sym.ty).srcLocOrNull(pt.zcu) orelse .unneeded,
+ },
.output_mode = comp.config.output_mode,
.link_mode = comp.config.link_mode,
.pic = comp.root_mod.pic,
@@ -8144,28 +8135,21 @@ fn genTypedValue(func: *Func, val: Value) InnerError!MCValue {
const pt = func.pt;
const lf = func.bin_file;
- const src_loc = func.src_loc;
- const result: codegen.GenResult = if (val.isUndef(pt.zcu))
- switch (try lf.lowerUav(pt, val.toIntern(), .none, src_loc)) {
- .sym_index => |sym_index| .{ .mcv = .{ .load_symbol = sym_index } },
- .fail => |em| .{ .fail = em },
- }
+ const result: codegen.MCValue = if (val.isUndef(pt.zcu))
+ .{ .load_symbol = try lf.lowerUav(pt, val.toIntern(), .none) }
else
- try codegen.genTypedValue(lf, pt, src_loc, val, func.target);
+ try codegen.genTypedValue(lf, pt, val, func.target);
const mcv: MCValue = switch (result) {
- .mcv => |mcv| switch (mcv) {
- .none => .none,
- .undef => unreachable,
- .lea_symbol => |sym_index| .{ .lea_symbol = .{ .sym = sym_index } },
- .load_symbol => |sym_index| .{ .load_symbol = .{ .sym = sym_index } },
- .immediate => |imm| .{ .immediate = imm },
- .memory => |addr| .{ .memory = addr },
- .load_got, .load_direct, .lea_direct => {
- return func.fail("TODO: genTypedValue {s}", .{@tagName(mcv)});
- },
+ .none => .none,
+ .undef => unreachable,
+ .lea_symbol => |sym_index| .{ .lea_symbol = .{ .sym = sym_index } },
+ .load_symbol => |sym_index| .{ .load_symbol = .{ .sym = sym_index } },
+ .immediate => |imm| .{ .immediate = imm },
+ .memory => |addr| .{ .memory = addr },
+ .load_got, .load_direct, .lea_direct => {
+ return func.fail("TODO: genTypedValue {s}", .{@tagName(result)});
},
- .fail => |msg| return func.failMsg(msg),
};
return mcv;
}
@@ -8353,24 +8337,24 @@ fn wantSafety(func: *Func) bool {
};
}
-fn fail(func: *const Func, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {
+fn fail(func: *const Func, comptime format: []const u8, args: anytype) error{ OutOfMemory, AlreadyReported } {
@branchHint(.cold);
const zcu = func.pt.zcu;
switch (func.owner) {
.nav_index => |i| return zcu.codegenFail(i, format, args),
.lazy_sym => |s| return zcu.codegenFailType(s.ty, format, args),
}
- return error.CodegenFail;
+ return error.AlreadyReported;
}
-fn failMsg(func: *const Func, msg: *ErrorMsg) error{ OutOfMemory, CodegenFail } {
+fn failMsg(func: *const Func, msg: *ErrorMsg) error{ OutOfMemory, AlreadyReported } {
@branchHint(.cold);
const zcu = func.pt.zcu;
switch (func.owner) {
.nav_index => |i| return zcu.codegenFailMsg(i, msg),
.lazy_sym => |s| return zcu.codegenFailTypeMsg(s.ty, msg),
}
- return error.CodegenFail;
+ return error.AlreadyReported;
}
fn parseRegName(name: []const u8) ?Register {
diff --git a/src/codegen/riscv64/Mir.zig b/src/codegen/riscv64/Mir.zig
@@ -107,12 +107,11 @@ pub fn emit(
mir: Mir,
lf: *link.File,
pt: Zcu.PerThread,
- src_loc: Zcu.LazySrcLoc,
func_index: InternPool.Index,
atom_index: link.File.AtomId,
w: *std.Io.Writer,
debug_output: link.File.DebugInfoOutput,
-) (codegen.CodeGenError || std.Io.Writer.Error)!void {
+) (codegen.Error || std.Io.Writer.Error)!void {
_ = atom_index;
const zcu = pt.zcu;
const comp = zcu.comp;
@@ -127,7 +126,7 @@ pub fn emit(
.allocator = gpa,
.mir = mir,
.cc = fn_info.cc,
- .src_loc = src_loc,
+ .src_loc = zcu.navSrcLoc(nav),
.output_mode = comp.config.output_mode,
.link_mode = comp.config.link_mode,
.pic = mod.pic,
diff --git a/src/codegen/sparc64/CodeGen.zig b/src/codegen/sparc64/CodeGen.zig
@@ -19,7 +19,6 @@ const Air = @import("../../Air.zig");
const Mir = @import("Mir.zig");
const Emit = @import("Emit.zig");
const Type = @import("../../Type.zig");
-const CodeGenError = codegen.CodeGenError;
const Endian = std.lang.Endian;
const Alignment = InternPool.Alignment;
@@ -39,7 +38,7 @@ const gp = abi.RegisterClass.gp;
const Self = @This();
-const InnerError = CodeGenError || error{OutOfRegisters};
+const InnerError = codegen.Error || error{OutOfRegisters};
pub fn legalizeFeatures(_: *const std.Target) ?*const Air.Legalize.Features {
return null;
@@ -57,12 +56,10 @@ liveness: Air.Liveness,
bin_file: *link.File,
target: *const std.Target,
func_index: InternPool.Index,
-err_msg: ?*ErrorMsg,
args: []MCValue,
ret_mcv: MCValue,
fn_type: Type,
arg_index: usize,
-src_loc: Zcu.LazySrcLoc,
stack_align: Alignment,
/// MIR Instructions
@@ -264,11 +261,10 @@ const BigTomb = struct {
pub fn generate(
lf: *link.File,
pt: Zcu.PerThread,
- src_loc: Zcu.LazySrcLoc,
func_index: InternPool.Index,
air: *const Air,
liveness: *const ?Air.Liveness,
-) CodeGenError!Mir {
+) codegen.Error!Mir {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const func = zcu.funcInfo(func_index);
@@ -292,13 +288,11 @@ pub fn generate(
.target = target,
.bin_file = lf,
.func_index = func_index,
- .err_msg = null,
.args = undefined, // populated after `resolveCallingConventionValues`
.ret_mcv = undefined, // populated after `resolveCallingConventionValues`
.fn_type = func_ty,
.arg_index = 0,
.branch_stack = &branch_stack,
- .src_loc = src_loc,
.stack_align = undefined,
.end_di_line = func.rbrace_line,
.end_di_column = func.rbrace_column,
@@ -307,10 +301,7 @@ pub fn generate(
defer function.blocks.deinit(gpa);
defer function.exitlude_jump_relocs.deinit(gpa);
- var call_info = function.resolveCallingConventionValues(func_ty, .callee) catch |err| switch (err) {
- error.CodegenFail => |e| return e,
- else => |e| return e,
- };
+ var call_info = try function.resolveCallingConventionValues(func_ty, .callee);
defer call_info.deinit(&function);
function.args = call_info.args;
@@ -319,7 +310,6 @@ pub fn generate(
function.max_end_stack = call_info.stack_byte_count;
function.gen() catch |err| switch (err) {
- error.CodegenFail => |e| return e,
error.OutOfRegisters => return function.fail("ran out of registers (Zig compiler bug)", .{}),
else => |e| return e,
};
@@ -3446,15 +3436,15 @@ fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type)
}
}
-fn fail(self: *Self, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {
+fn fail(self: *Self, comptime format: []const u8, args: anytype) error{ OutOfMemory, AlreadyReported } {
@branchHint(.cold);
const zcu = self.pt.zcu;
const func = zcu.funcInfo(self.func_index);
- const msg = try ErrorMsg.create(zcu.gpa, self.src_loc, format, args);
+ const msg = try ErrorMsg.create(zcu.gpa, zcu.navSrcLoc(func.owner_nav), format, args);
return zcu.codegenFailMsg(func.owner_nav, msg);
}
-fn failMsg(self: *Self, msg: *ErrorMsg) error{ OutOfMemory, CodegenFail } {
+fn failMsg(self: *Self, msg: *ErrorMsg) error{ OutOfMemory, AlreadyReported } {
@branchHint(.cold);
const zcu = self.pt.zcu;
const func = zcu.funcInfo(self.func_index);
@@ -4036,21 +4026,14 @@ fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {
const mcv: MCValue = switch (try codegen.genTypedValue(
self.bin_file,
pt,
- self.src_loc,
val,
self.target,
)) {
- .mcv => |mcv| switch (mcv) {
- .none => .none,
- .undef => .undef,
- .load_got, .load_symbol, .load_direct, .lea_symbol, .lea_direct => unreachable, // TODO
- .immediate => |imm| .{ .immediate = imm },
- .memory => |addr| .{ .memory = addr },
- },
- .fail => |msg| {
- self.err_msg = msg;
- return error.CodegenFail;
- },
+ .none => .none,
+ .undef => .undef,
+ .load_got, .load_symbol, .load_direct, .lea_symbol, .lea_direct => unreachable, // TODO
+ .immediate => |imm| .{ .immediate = imm },
+ .memory => |addr| .{ .memory = addr },
};
return mcv;
}
diff --git a/src/codegen/sparc64/Mir.zig b/src/codegen/sparc64/Mir.zig
@@ -378,12 +378,11 @@ pub fn emit(
mir: Mir,
lf: *link.File,
pt: Zcu.PerThread,
- src_loc: Zcu.LazySrcLoc,
func_index: InternPool.Index,
atom_index: link.File.AtomId,
w: *std.Io.Writer,
debug_output: link.File.DebugInfoOutput,
-) (codegen.CodeGenError || std.Io.Writer.Error)!void {
+) (codegen.Error || std.Io.Writer.Error)!void {
_ = atom_index;
const zcu = pt.zcu;
const func = zcu.funcInfo(func_index);
@@ -394,7 +393,7 @@ pub fn emit(
.bin_file = lf,
.debug_output = debug_output,
.target = &mod.resolved_target.result,
- .src_loc = src_loc,
+ .src_loc = zcu.navSrcLoc(nav),
.w = w,
.prev_di_pc = 0,
.prev_di_line = func.lbrace_line,
diff --git a/src/codegen/spirv/CodeGen.zig b/src/codegen/spirv/CodeGen.zig
@@ -156,7 +156,6 @@ inst_results: std.AutoHashMapUnmanaged(Air.Inst.Index, Id) = .empty,
id_scratch: std.ArrayList(Id) = .empty,
prologue: Section = .{},
body: Section = .{},
-error_msg: ?*Zcu.ErrorMsg = null,
pub fn deinit(cg: *CodeGen) void {
const gpa = cg.module.gpa;
@@ -168,7 +167,7 @@ pub fn deinit(cg: *CodeGen) void {
cg.body.deinit(gpa);
}
-const Error = error{ CodegenFail, OutOfMemory };
+const Error = error{ AlreadyReported, OutOfMemory };
pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void {
const gpa = cg.module.gpa;
@@ -363,11 +362,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void {
pub fn fail(cg: *CodeGen, comptime format: []const u8, args: anytype) Error {
@branchHint(.cold);
- const zcu = cg.module.zcu;
- const src_loc = zcu.navSrcLoc(cg.owner_nav);
- assert(cg.error_msg == null);
- cg.error_msg = try Zcu.ErrorMsg.create(zcu.gpa, src_loc, format, args);
- return error.CodegenFail;
+ return cg.module.zcu.codegenFail(cg.owner_nav, format, args);
}
pub fn todo(cg: *CodeGen, comptime format: []const u8, args: anytype) Error {
@@ -5934,14 +5929,14 @@ fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
// them as notes here.
// TODO: Translate proper error locations.
assert(ass.errors.items.len != 0);
- assert(cg.error_msg == null);
- const src_loc = zcu.navSrcLoc(cg.owner_nav);
- cg.error_msg = try Zcu.ErrorMsg.create(zcu.gpa, src_loc, "failed to assemble SPIR-V inline assembly", .{});
- const notes = try zcu.gpa.alloc(Zcu.ErrorMsg, ass.errors.items.len);
+ const msg: *Zcu.ErrorMsg = msg: {
+ const src_loc = zcu.navSrcLoc(cg.owner_nav);
+ var msg: *Zcu.ErrorMsg = try .create(zcu.gpa, src_loc, "failed to assemble SPIR-V inline assembly", .{});
+ errdefer msg.destroy(zcu.gpa);
- // Sub-scope to prevent `return error.CodegenFail` from running the errdefers.
- {
+ const notes = try zcu.gpa.alloc(Zcu.ErrorMsg, ass.errors.items.len);
errdefer zcu.gpa.free(notes);
+
var i: usize = 0;
errdefer for (notes[0..i]) |*note| {
note.deinit(zcu.gpa);
@@ -5950,9 +5945,10 @@ fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
while (i < ass.errors.items.len) : (i += 1) {
notes[i] = try Zcu.ErrorMsg.init(zcu.gpa, src_loc, "{s}", .{ass.errors.items[i].msg});
}
- }
- cg.error_msg.?.notes = notes;
- return error.CodegenFail;
+
+ break :msg msg;
+ };
+ return zcu.codegenFailMsg(cg.owner_nav, msg);
},
else => |others| return others,
};
diff --git a/src/codegen/wasm/CodeGen.zig b/src/codegen/wasm/CodeGen.zig
@@ -329,7 +329,7 @@ const bookkeeping_init = if (std.debug.runtime_safety) @as(usize, 0) else {};
const InnerError = error{
OutOfMemory,
/// An error occurred when trying to lower AIR to MIR.
- CodegenFail,
+ AlreadyReported,
/// Compiler implementation could not handle a large integer.
Overflow,
} || link.File.UpdateDebugInfoError;
@@ -355,7 +355,7 @@ pub fn deinit(cg: *CodeGen) void {
cg.* = undefined;
}
-pub fn fail(cg: *CodeGen, comptime fmt: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {
+pub fn fail(cg: *CodeGen, comptime fmt: []const u8, args: anytype) error{ OutOfMemory, AlreadyReported } {
const zcu = cg.pt.zcu;
const func = zcu.funcInfo(cg.func_index);
return zcu.codegenFail(func.owner_nav, fmt, args);
@@ -756,21 +756,17 @@ fn ensureAllocLocal(cg: *CodeGen, ty: Type) InnerError!WValue {
pub const Error = error{
OutOfMemory,
- /// Compiler was asked to operate on a number larger than supported.
- Overflow,
/// Indicates the error is already stored in Zcu `failed_codegen`.
- CodegenFail,
+ AlreadyReported,
};
pub fn generate(
bin_file: *link.File,
pt: Zcu.PerThread,
- src_loc: Zcu.LazySrcLoc,
func_index: InternPool.Index,
air: *const Air,
liveness: *const ?Air.Liveness,
) Error!Mir {
- _ = src_loc;
_ = bin_file;
const zcu = pt.zcu;
const gpa = zcu.gpa;
@@ -814,9 +810,8 @@ pub fn generate(
try code_gen.mir_func_tys.putNoClobber(gpa, fn_ty.toIntern(), {});
return generateInner(&code_gen, any_returns) catch |err| switch (err) {
- error.CodegenFail,
+ error.AlreadyReported,
error.OutOfMemory,
- error.Overflow,
=> |e| return e,
else => |e| return code_gen.fail("failed to generate function: {s}", .{@errorName(e)}),
};
diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig
@@ -31,7 +31,7 @@ const RegisterManager = abi.RegisterManager;
const RegisterLock = RegisterManager.RegisterLock;
const FrameIndex = bits.FrameIndex;
-const InnerError = codegen.CodeGenError || error{OutOfRegisters};
+const InnerError = codegen.Error || error{OutOfRegisters};
pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
return comptime &.initMany(&.{
@@ -106,7 +106,6 @@ va_info: union {
ret_mcv: InstTracking,
err_ret_trace_reg: Register,
fn_type: Type,
-src_loc: Zcu.LazySrcLoc,
eflags_inst: ?Air.Inst.Index = null,
@@ -869,11 +868,10 @@ const CodeGen = @This();
pub fn generate(
bin_file: *link.File,
pt: Zcu.PerThread,
- src_loc: Zcu.LazySrcLoc,
func_index: InternPool.Index,
air: *const Air,
liveness: *const ?Air.Liveness,
-) codegen.CodeGenError!Mir {
+) codegen.Error!Mir {
_ = bin_file;
const zcu = pt.zcu;
const gpa = zcu.gpa;
@@ -898,7 +896,6 @@ pub fn generate(
.ret_mcv = undefined, // populated after `resolveCallingConventionValues`
.err_ret_trace_reg = undefined, // populated after `resolveCallingConventionValues`
.fn_type = fn_type,
- .src_loc = src_loc,
};
defer {
function.frame_allocs.deinit(gpa);
@@ -937,10 +934,7 @@ pub fn generate(
);
const fn_info = zcu.typeToFunc(fn_type).?;
- var call_info = function.resolveCallingConventionValues(fn_info, &.{}, .args_frame) catch |err| switch (err) {
- error.CodegenFail => |e| return e,
- else => |e| return e,
- };
+ var call_info = try function.resolveCallingConventionValues(fn_info, &.{}, .args_frame);
defer call_info.deinit(&function);
function.args = call_info.args;
@@ -983,7 +977,6 @@ pub fn generate(
}
function.gen(&file.zir.?, func_zir.inst, func.comptime_args, call_info.air_arg_count) catch |err| switch (err) {
- error.CodegenFail => |e| return e,
error.OutOfRegisters => return function.fail("ran out of registers (Zig compiler bug)", .{}),
else => |e| return e,
};
@@ -1027,12 +1020,11 @@ pub fn getTmpMir(cg: *CodeGen) Mir {
pub fn generateLazy(
bin_file: *link.File,
pt: Zcu.PerThread,
- src_loc: Zcu.LazySrcLoc,
lazy_sym: link.File.LazySymbol,
atom_id: link.File.AtomId,
w: *std.Io.Writer,
debug_output: link.File.DebugInfoOutput,
-) codegen.CodeGenError!void {
+) codegen.Error!void {
const gpa = pt.zcu.gpa;
// This function is for generating global code, so we use the root module.
const mod = pt.zcu.comp.root_mod;
@@ -1050,7 +1042,6 @@ pub fn generateLazy(
.ret_mcv = undefined,
.err_ret_trace_reg = undefined,
.fn_type = undefined,
- .src_loc = src_loc,
};
defer {
function.inst_tracking.deinit(gpa);
@@ -1068,12 +1059,11 @@ pub fn generateLazy(
}
function.genLazy(lazy_sym) catch |err| switch (err) {
- error.CodegenFail => |e| return e,
error.OutOfRegisters => return function.fail("ran out of registers (Zig compiler bug)", .{}),
else => |e| return e,
};
- try function.getTmpMir().emitLazy(bin_file, pt, src_loc, lazy_sym, atom_id, w, debug_output);
+ try function.getTmpMir().emitLazy(bin_file, pt, lazy_sym, atom_id, w, debug_output);
}
const FormatNavData = struct {
@@ -1111,7 +1101,10 @@ fn formatWipMir(data: FormatWipMirData, w: *Writer) Writer.Error!void {
.allocator = data.self.gpa,
.mir = data.self.getTmpMir(),
.cc = .auto,
- .src_loc = data.self.src_loc,
+ .src_loc = switch (data.self.owner) {
+ .nav_index => |nav| data.self.pt.zcu.navSrcLoc(nav),
+ .lazy_sym => |lazy_sym| Type.fromInterned(lazy_sym.ty).srcLocOrNull(data.self.pt.zcu) orelse .unneeded,
+ },
};
var first = true;
for ((lower.lowerMir(data.inst) catch |err| switch (err) {
@@ -181508,7 +181501,7 @@ fn resolveCallingConventionValues(
return result;
}
-fn fail(cg: *CodeGen, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {
+fn fail(cg: *CodeGen, comptime format: []const u8, args: anytype) error{ OutOfMemory, AlreadyReported } {
@branchHint(.cold);
const zcu = cg.pt.zcu;
return switch (cg.owner) {
diff --git a/src/codegen/x86_64/Emit.zig b/src/codegen/x86_64/Emit.zig
@@ -17,6 +17,7 @@ relocs: std.ArrayList(Reloc),
table_relocs: std.ArrayList(TableReloc),
pub const Error = Lower.Error || error{
+ AlreadyReported,
EmitFail,
NotFile,
} || std.posix.MMapError || std.posix.MRemapError || link.File.UpdateDebugInfoError;
@@ -101,20 +102,11 @@ pub fn emitMir(emit: *Emit) Error!void {
.inst => |inst| .{ .inst = inst },
.table => .table,
.nav => |nav| {
- const symbol_id = switch (try codegen.genNavRef(
+ const symbol_id = try codegen.genNavRef(
emit.bin_file,
emit.pt,
- emit.lower.src_loc,
nav,
- emit.lower.target,
- )) {
- .sym_index => |symbol_id| symbol_id,
- .fail => |em| {
- assert(emit.lower.err_msg == null);
- emit.lower.err_msg = em;
- return error.EmitFail;
- },
- };
+ );
const target_symbol: RelocInfo.Target.Symbol = if (ip.getNav(nav).getExtern(ip)) |@"extern"| .{
.symbol = symbol_id,
.is_extern = switch (@"extern".visibility) {
@@ -133,19 +125,11 @@ pub fn emitMir(emit: *Emit) Error!void {
}
},
.uav => |uav| .{ .symbol = .{
- .symbol = switch (try emit.bin_file.lowerUav(
+ .symbol = try emit.bin_file.lowerUav(
emit.pt,
uav.val,
Type.fromInterned(uav.orig_ty).ptrAlignment(emit.pt.zcu),
- emit.lower.src_loc,
- )) {
- .sym_index => |symbol_id| symbol_id,
- .fail => |em| {
- assert(emit.lower.err_msg == null);
- emit.lower.err_msg = em;
- return error.EmitFail;
- },
- },
+ ),
.is_extern = false,
} },
.lazy_sym => |lazy_sym| .{ .symbol = .{
@@ -168,17 +152,14 @@ pub fn emitMir(emit: *Emit) Error!void {
.extern_func => |extern_func| .{ .symbol = .{
.symbol = if (emit.bin_file.cast(.elf)) |elf_file|
@enumFromInt(try elf_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, null))
- else if (emit.bin_file.cast(.elf2)) |elf| elf.externSymbol(.{
+ else if (emit.bin_file.cast(.elf2)) |elf| try elf.externSymbol(.{
.name = extern_func.toSlice(&emit.lower.mir).?,
.lib_name = switch (comp.compiler_rt_strat) {
.none, .lib, .obj, .zcu => null,
.dyn_lib => "compiler_rt",
},
.type = .FUNC,
- }) catch |err| switch (err) {
- error.LinkOnceUnsupported => unreachable,
- else => |e| return e,
- } else if (emit.bin_file.cast(.macho)) |macho_file|
+ }) else if (emit.bin_file.cast(.macho)) |macho_file|
@enumFromInt(try macho_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, null))
else if (emit.bin_file.cast(.coff2)) |coff| @enumFromInt(@intFromEnum(try coff.globalSymbol(
extern_func.toSlice(&emit.lower.mir).?,
@@ -313,14 +294,11 @@ pub fn emitMir(emit: *Emit) Error!void {
.symbol = if (emit.bin_file.cast(.elf)) |elf_file| @enumFromInt(try elf_file.getGlobalSymbol(
"__tls_get_addr",
if (comp.config.link_libc) "c" else null,
- )) else if (emit.bin_file.cast(.elf2)) |elf| elf.externSymbol(.{
+ )) else if (emit.bin_file.cast(.elf2)) |elf| try elf.externSymbol(.{
.name = "__tls_get_addr",
.lib_name = if (comp.config.link_libc) "c" else null,
.type = .FUNC,
- }) catch |err| switch (err) {
- error.LinkOnceUnsupported => unreachable,
- else => |e| return e,
- } else unreachable,
+ }) else unreachable,
.is_extern = true,
} },
}});
@@ -584,37 +562,16 @@ pub fn emitMir(emit: *Emit) Error!void {
.none => .{ .constu = 0 },
.reg => |reg| .{ .breg = reg.dwarfNum() },
.frame, .table, .rip_inst => unreachable,
- .nav => |nav| .{ .addr_reloc = switch (codegen.genNavRef(
+ .nav => |nav| .{ .addr_reloc = try codegen.genNavRef(
emit.bin_file,
emit.pt,
- emit.lower.src_loc,
nav,
- emit.lower.target,
- ) catch |err| switch (err) {
- error.CodegenFail,
- => return emit.fail("unable to codegen: {s}", .{@errorName(err)}),
- else => |e| return e,
- }) {
- .sym_index => |sym_index| sym_index,
- .fail => |em| {
- assert(emit.lower.err_msg == null);
- emit.lower.err_msg = em;
- return error.EmitFail;
- },
- } },
- .uav => |uav| .{ .addr_reloc = switch (try emit.bin_file.lowerUav(
+ ) },
+ .uav => |uav| .{ .addr_reloc = try emit.bin_file.lowerUav(
emit.pt,
uav.val,
Type.fromInterned(uav.orig_ty).ptrAlignment(emit.pt.zcu),
- emit.lower.src_loc,
- )) {
- .sym_index => |sym_index| sym_index,
- .fail => |em| {
- assert(emit.lower.err_msg == null);
- emit.lower.err_msg = em;
- return error.EmitFail;
- },
- } },
+ ) },
.lazy_sym, .extern_func => unreachable,
};
break :base &loc_buf[0];
@@ -666,7 +623,6 @@ pub fn emitMir(emit: *Emit) Error!void {
const local = &emit.lower.mir.locals[local_index];
local_index += 1;
try dwarf.genLocalConstDebugInfo(
- emit.lower.src_loc,
switch (mir_inst.ops) {
else => unreachable,
.pseudo_dbg_arg_val => .comptime_arg,
diff --git a/src/codegen/x86_64/Lower.zig b/src/codegen/x86_64/Lower.zig
@@ -49,8 +49,8 @@ pub const Error = error{
LowerFail,
InvalidInstruction,
CannotEncode,
- CodegenFail,
-} || codegen.GenerateSymbolError;
+ AlreadyReported,
+} || link.Error;
pub const Reloc = struct {
lowered_inst_index: ResultInstIndex,
diff --git a/src/codegen/x86_64/Mir.zig b/src/codegen/x86_64/Mir.zig
@@ -1974,12 +1974,11 @@ pub fn emit(
mir: Mir,
lf: *link.File,
pt: Zcu.PerThread,
- src_loc: Zcu.LazySrcLoc,
func_index: InternPool.Index,
atom_id: link.File.AtomId,
w: *std.Io.Writer,
debug_output: link.File.DebugInfoOutput,
-) codegen.CodeGenError!void {
+) codegen.Error!void {
const zcu = pt.zcu;
const comp = zcu.comp;
const gpa = comp.gpa;
@@ -1993,7 +1992,7 @@ pub fn emit(
.allocator = gpa,
.mir = mir,
.cc = fn_info.cc,
- .src_loc = src_loc,
+ .src_loc = zcu.navSrcLoc(nav),
},
.bin_file = lf,
.pt = pt,
@@ -2028,12 +2027,11 @@ pub fn emitLazy(
mir: Mir,
lf: *link.File,
pt: Zcu.PerThread,
- src_loc: Zcu.LazySrcLoc,
lazy_sym: link.File.LazySymbol,
atom_id: link.File.AtomId,
w: *std.Io.Writer,
debug_output: link.File.DebugInfoOutput,
-) codegen.CodeGenError!void {
+) codegen.Error!void {
const zcu = pt.zcu;
const comp = zcu.comp;
const gpa = comp.gpa;
@@ -2044,7 +2042,7 @@ pub fn emitLazy(
.allocator = gpa,
.mir = mir,
.cc = .auto,
- .src_loc = src_loc,
+ .src_loc = Zcu.Type.fromInterned(lazy_sym.ty).srcLocOrNull(zcu) orelse .unneeded,
},
.bin_file = lf,
.pt = pt,
diff --git a/src/link.zig b/src/link.zig
@@ -31,6 +31,12 @@ pub const LdScript = @import("link/LdScript.zig");
pub const Queue = @import("link/Queue.zig");
pub const ConstPool = @import("link/ConstPool.zig");
+pub const Error = Allocator.Error || Io.Cancelable || error{
+ /// An error message has already been stored in persistent state on `Compilation` or `Zcu`, for
+ /// instance in `Compilation.link_diags`.
+ AlreadyReported,
+};
+
pub const Diags = struct {
/// Stored here so that function definitions can distinguish between
/// needing an allocator for things besides error reporting.
@@ -112,7 +118,7 @@ pub const Diags = struct {
err: ErrorWithNotes,
comptime format: []const u8,
args: anytype,
- ) error{OutOfMemory}!void {
+ ) Allocator.Error!void {
const gpa = err.diags.gpa;
const err_msg = &err.diags.msgs.items[err.index];
err_msg.msg = try std.fmt.allocPrint(gpa, format, args);
@@ -212,16 +218,16 @@ pub const Diags = struct {
}
}
- pub fn fail(diags: *Diags, comptime format: []const u8, args: anytype) error{LinkFailure} {
+ pub fn fail(diags: *Diags, comptime format: []const u8, args: anytype) error{AlreadyReported} {
@branchHint(.cold);
addError(diags, format, args);
- return error.LinkFailure;
+ return error.AlreadyReported;
}
- pub fn failSourceLocation(diags: *Diags, sl: SourceLocation, comptime format: []const u8, args: anytype) error{LinkFailure} {
+ pub fn failSourceLocation(diags: *Diags, sl: SourceLocation, comptime format: []const u8, args: anytype) error{AlreadyReported} {
@branchHint(.cold);
addErrorSourceLocation(diags, sl, format, args);
- return error.LinkFailure;
+ return error.AlreadyReported;
}
pub fn addError(diags: *Diags, comptime format: []const u8, args: anytype) void {
@@ -251,7 +257,7 @@ pub const Diags = struct {
});
}
- pub fn addErrorWithNotes(diags: *Diags, note_count: usize) error{OutOfMemory}!ErrorWithNotes {
+ pub fn addErrorWithNotes(diags: *Diags, note_count: usize) Allocator.Error!ErrorWithNotes {
@branchHint(.cold);
const gpa = diags.gpa;
const io = diags.io;
@@ -261,7 +267,7 @@ pub const Diags = struct {
return addErrorWithNotesAssumeCapacity(diags, note_count);
}
- pub fn addErrorWithNotesAssumeCapacity(diags: *Diags, note_count: usize) error{OutOfMemory}!ErrorWithNotes {
+ pub fn addErrorWithNotesAssumeCapacity(diags: *Diags, note_count: usize) Allocator.Error!ErrorWithNotes {
@branchHint(.cold);
const gpa = diags.gpa;
const index = diags.msgs.items.len;
@@ -351,10 +357,10 @@ pub const Diags = struct {
path: Path,
comptime format: []const u8,
args: anytype,
- ) error{LinkFailure} {
+ ) error{AlreadyReported} {
@branchHint(.cold);
addParseError(diags, path, format, args);
- return error.LinkFailure;
+ return error.AlreadyReported;
}
pub fn setAllocFailure(diags: *Diags) void {
@@ -752,11 +758,6 @@ pub const File = struct {
none,
};
pub const UpdateDebugInfoError = Dwarf.UpdateError;
- pub const FlushDebugInfoError = Dwarf.FlushError;
-
- /// Note that `LinkFailure` is not a member of this error set because the error message
- /// must be attached to `Zcu.failed_codegen` rather than `Compilation.link_diags`.
- pub const UpdateNavError = codegen.CodeGenError;
/// Opaque identifier for a function currently being emitted.
///
@@ -775,7 +776,7 @@ pub const File = struct {
/// be created. This symbol may get resolved once all relocatables are (re-)linked.
/// Optionally, it is possible to specify where to expect the symbol defined if it
/// is an import.
- pub fn getGlobalSymbol(base: *File, name: []const u8, lib_name: ?[]const u8) UpdateNavError!SymbolId {
+ pub fn getGlobalSymbol(base: *File, name: []const u8, lib_name: ?[]const u8) Error!SymbolId {
log.debug("getGlobalSymbol '{s}' (expected in '{?s}')", .{ name, lib_name });
switch (base.tag) {
.lld => unreachable,
@@ -790,7 +791,7 @@ pub const File = struct {
/// May be called before or after updateExports for any given Nav.
/// Asserts that the ZCU is not using the LLVM backend.
- fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) UpdateNavError!void {
+ fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) Error!void {
assert(base.comp.zcu.?.llvm_object == null);
const nav = pt.zcu.intern_pool.getNav(nav_index);
assert(nav.resolved.?.value != .none);
@@ -804,14 +805,8 @@ pub const File = struct {
}
}
- pub const UpdateContainerTypeError = error{
- OutOfMemory,
- /// `Zcu.failed_types` is already populated with the error message.
- TypeFailureReported,
- };
-
/// Never called when LLVM is codegenning the ZCU.
- fn updateContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) UpdateContainerTypeError!void {
+ fn updateContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) Error!void {
assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
.lld => unreachable,
@@ -824,7 +819,7 @@ pub const File = struct {
}
/// Never called when LLVM is codegenning the ZCU.
- fn clearContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index) UpdateContainerTypeError!void {
+ fn clearContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index) Error!void {
assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
.lld => unreachable,
@@ -847,7 +842,7 @@ pub const File = struct {
/// that `mir.deinit` remains legal for the caller. For instance, the callee can
/// take ownership of an embedded slice and replace it with `&.{}` in `mir`.
mir: *codegen.AnyMir,
- ) UpdateNavError!void {
+ ) Error!void {
assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
.lld => unreachable,
@@ -860,16 +855,10 @@ pub const File = struct {
}
}
- pub const UpdateLineNumberError = error{
- OutOfMemory,
- Overflow,
- LinkFailure,
- };
-
/// On an incremental update, fixup the line number of all `Nav`s at the given `TrackedInst`, because
/// its line number has changed. The ZIR instruction `ti_id` has tag `.declaration`.
/// Never called when LLVM is codegenning the ZCU.
- fn updateLineNumber(base: *File, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) UpdateLineNumberError!void {
+ fn updateLineNumber(base: *File, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) Error!void {
assert(base.comp.zcu.?.llvm_object == null);
{
const ti = ti_id.resolveFull(&pt.zcu.intern_pool).?;
@@ -918,7 +907,7 @@ pub const File = struct {
}
}
- pub fn idle(base: *File, tid: Zcu.PerThread.Id) !bool {
+ pub fn idle(base: *File, tid: Zcu.PerThread.Id) Error!bool {
switch (base.tag) {
else => return false,
inline .elf2, .coff2 => |tag| {
@@ -928,7 +917,7 @@ pub const File = struct {
}
}
- pub fn updateErrorData(base: *File, pt: Zcu.PerThread) !void {
+ pub fn updateErrorData(base: *File, pt: Zcu.PerThread) Error!void {
switch (base.tag) {
else => {},
inline .elf2, .coff2 => |tag| {
@@ -938,14 +927,9 @@ pub const File = struct {
}
}
- pub const FlushError = Io.Cancelable || Allocator.Error || error{
- /// Indicates an error will be present in `Compilation.link_diags`.
- LinkFailure,
- };
-
/// Commit pending changes and write headers. Takes into account final output mode.
/// `arena` has the lifetime of the call to `Compilation.update`.
- pub fn flush(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void {
+ pub fn flush(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) Error!void {
const comp = base.comp;
const io = comp.io;
if (comp.clang_preprocessor_mode == .yes or comp.clang_preprocessor_mode == .pch) {
@@ -985,11 +969,6 @@ pub const File = struct {
}
}
- pub const UpdateExportsError = error{
- OutOfMemory,
- AnalysisFail,
- };
-
/// This is called for every exported thing. `exports` is almost always
/// a list of size 1, meaning that `exported` is exported once. However, it is possible
/// to export the same thing with multiple different symbol names (aliases).
@@ -1000,7 +979,7 @@ pub const File = struct {
pt: Zcu.PerThread,
exported: Zcu.Exported,
export_indices: []const Zcu.Export.Index,
- ) UpdateExportsError!void {
+ ) Error!void {
assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
.lld => unreachable,
@@ -1031,7 +1010,7 @@ pub const File = struct {
/// May be called before or after updateFunc/updateNav therefore it is up to the linker to allocate
/// the block/atom.
/// Never called when LLVM is codegenning the ZCU.
- pub fn getNavVAddr(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: RelocInfo) !u64 {
+ pub fn getNavVAddr(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: RelocInfo) Error!u64 {
assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
.lld => unreachable,
@@ -1052,8 +1031,7 @@ pub const File = struct {
pt: Zcu.PerThread,
decl_val: InternPool.Index,
decl_align: InternPool.Alignment,
- src_loc: Zcu.LazySrcLoc,
- ) !codegen.SymbolResult {
+ ) Error!SymbolId {
assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
.lld => unreachable,
@@ -1063,13 +1041,13 @@ pub const File = struct {
.plan9 => unreachable,
inline else => |tag| {
dev.check(tag.devFeature());
- return @as(*tag.Type(), @fieldParentPtr("base", base)).lowerUav(pt, decl_val, decl_align, src_loc);
+ return @as(*tag.Type(), @fieldParentPtr("base", base)).lowerUav(pt, decl_val, decl_align);
},
}
}
/// Never called when LLVM is codegenning the ZCU.
- pub fn getUavVAddr(base: *File, decl_val: InternPool.Index, reloc_info: RelocInfo) !u64 {
+ pub fn getUavVAddr(base: *File, decl_val: InternPool.Index, reloc_info: RelocInfo) Error!u64 {
assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
.lld => unreachable,
@@ -1217,7 +1195,7 @@ pub const File = struct {
/// Called when all linker inputs have been sent via `loadInput`. After
/// this, `loadInput` will not be called anymore.
- pub fn prelink(base: *File) FlushError!void {
+ pub fn prelink(base: *File) Error!void {
assert(!base.post_prelink);
// In this case, an object file is created by the LLVM backend, so
@@ -1251,7 +1229,11 @@ pub const File = struct {
file_writer.pos = new_offset;
const size_u = std.math.cast(usize, size) orelse return error.Overflow;
const n = file_writer.interface.sendFileAll(&file_reader, .limited(size_u)) catch |err| switch (err) {
- error.ReadFailed => return file_reader.err.?,
+ error.ReadFailed => switch (file_reader.err.?) {
+ error.ConnectionResetByPeer => return error.Unexpected, // not a socket
+ error.SocketUnconnected => return error.Unexpected, // not a socket
+ else => |e| return e,
+ },
error.WriteFailed => return file_writer.err.?,
};
assert(n == size_u);
@@ -1367,7 +1349,7 @@ pub const File = struct {
nav_index: InternPool.Nav.Index,
comptime format: []const u8,
args: anytype,
- ) error{ CodegenFail, OutOfMemory } {
+ ) Zcu.CodegenFailError {
@branchHint(.cold);
return base.comp.zcu.?.codegenFail(nav_index, format, args);
}
@@ -1440,7 +1422,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
defer prog_node.end();
for (comp.link_inputs) |input| {
base.loadInput(input) catch |err| switch (err) {
- error.LinkFailure => return, // error reported via diags
+ error.AlreadyReported => return, // error reported via diags
else => |e| switch (input) {
.dso => |dso| diags.addParseError(dso.path, "failed to parse shared library: {s}", .{@errorName(e)}),
.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 {
.preferred_mode = .dynamic,
.search_strategy = .paths_first,
}) catch |archive_err| switch (archive_err) {
- error.LinkFailure => return, // error reported via diags
+ error.AlreadyReported => return, // error reported via diags
else => |e| diags.addParseError(dso_path, "failed to parse archive {f}: {s}", .{ archive_path, @errorName(e) }),
};
},
- error.LinkFailure => return, // error reported via diags
+ error.AlreadyReported => return, // error reported via diags
else => |e| diags.addParseError(dso_path, "failed to parse shared library: {s}", .{@errorName(e)}),
};
},
@@ -1504,7 +1486,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
.preferred_mode = .static,
.search_strategy = .no_fallback,
}) catch |err| switch (err) {
- error.LinkFailure => return, // error reported via diags
+ error.AlreadyReported => return, // error reported via diags
else => |e| diags.addParseError(path, "failed to parse archive: {s}", .{@errorName(e)}),
};
},
@@ -1515,7 +1497,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
const prog_node = comp.link_prog_node.start("Parse Object", 0);
defer prog_node.end();
base.openLoadObject(path) catch |err| switch (err) {
- error.LinkFailure => return, // error reported via diags
+ error.AlreadyReported => return, // error reported via diags
else => |e| diags.addParseError(path, "failed to parse object: {s}", .{@errorName(e)}),
};
},
@@ -1523,7 +1505,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
const prog_node = comp.link_prog_node.start("Parse Archive", 0);
defer prog_node.end();
base.openLoadArchive(load_archive.path, load_archive.must_link) catch |err| switch (err) {
- error.LinkFailure => return, // error reported via link_diags
+ error.AlreadyReported => return, // error reported via link_diags
else => |e| diags.addParseError(load_archive.path, "failed to parse archive: {s}", .{@errorName(e)}),
};
},
@@ -1534,7 +1516,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
.preferred_mode = .dynamic,
.search_strategy = .paths_first,
}) catch |err| switch (err) {
- error.LinkFailure => return, // error reported via link_diags
+ error.AlreadyReported => return, // error reported via link_diags
else => |e| diags.addParseError(path, "failed to parse shared library: {s}", .{@errorName(e)}),
};
},
@@ -1561,15 +1543,9 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void
};
} else if (comp.bin_file) |lf| {
lf.updateNav(pt, nav_index) catch |err| switch (err) {
+ error.Canceled => io.recancel(),
+ error.AlreadyReported => return,
error.OutOfMemory => diags.setAllocFailure(),
- error.CodegenFail => zcu.assertCodegenFailed(nav_index),
- error.Overflow, error.RelocationNotByteAligned => {
- switch (zcu.codegenFail(nav_index, "unable to codegen: {s}", .{@errorName(err)})) {
- error.CodegenFail => return,
- error.OutOfMemory => return diags.setAllocFailure(),
- }
- // Not a retryable failure.
- },
};
}
break :nav nav_index;
@@ -1594,14 +1570,9 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void
assert(zcu.llvm_object == null); // LLVM codegen doesn't produce MIR
if (comp.bin_file) |lf| {
lf.updateFunc(pt, func, &mir) catch |err| switch (err) {
+ error.Canceled => io.recancel(),
+ error.AlreadyReported => return,
error.OutOfMemory => return diags.setAllocFailure(),
- error.CodegenFail => return zcu.assertCodegenFailed(nav),
- error.Overflow, error.RelocationNotByteAligned => {
- switch (zcu.codegenFail(nav, "unable to codegen: {s}", .{@errorName(err)})) {
- error.OutOfMemory => return diags.setAllocFailure(),
- error.CodegenFail => return,
- }
- },
};
}
break :nav ip.indexToKey(func).func.owner_nav;
@@ -1618,7 +1589,8 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void
if (comp.bin_file) |lf| {
lf.updateContainerType(pt, container_update.ty, container_update.success) catch |err| switch (err) {
error.OutOfMemory => diags.setAllocFailure(),
- error.TypeFailureReported => assert(zcu.failed_types.contains(container_update.ty)),
+ error.Canceled => io.recancel(),
+ error.AlreadyReported => {},
};
}
}
@@ -1657,7 +1629,7 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void
}
}
}
-pub fn doIdleTask(comp: *Compilation, tid: Zcu.PerThread.Id) error{ OutOfMemory, LinkFailure }!bool {
+pub fn doIdleTask(comp: *Compilation, tid: Zcu.PerThread.Id) Error!bool {
return if (comp.bin_file) |lf| lf.idle(tid) else false;
}
/// 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)
};
} else if (comp.bin_file) |lf| {
lf.updateNav(pt, nav_index) catch |err| switch (err) {
+ error.Canceled => comp.io.recancel(),
+ error.AlreadyReported => return,
error.OutOfMemory => diags.setAllocFailure(),
- error.CodegenFail => zcu.assertCodegenFailed(nav_index),
- error.Overflow, error.RelocationNotByteAligned => {
- switch (zcu.codegenFail(nav_index, "unable to codegen: {s}", .{@errorName(err)})) {
- error.CodegenFail => return,
- error.OutOfMemory => return diags.setAllocFailure(),
- }
- // Not a retryable failure.
- },
};
}
}
@@ -1689,7 +1655,8 @@ pub fn updateErrorData(pt: Zcu.PerThread) void {
const comp = pt.zcu.comp;
if (comp.bin_file) |lf| lf.updateErrorData(pt) catch |err| switch (err) {
error.OutOfMemory => comp.link_diags.setAllocFailure(),
- error.LinkFailure => {},
+ error.Canceled => comp.io.recancel(),
+ error.AlreadyReported => {},
};
}
@@ -2428,19 +2395,19 @@ pub fn openDso(io: Io, path: Path, needed: bool, weak: bool, reexport: bool) !In
};
}
-pub fn openObjectInput(io: Io, diags: *Diags, path: Path) error{LinkFailure}!Input {
+pub fn openObjectInput(io: Io, diags: *Diags, path: Path) error{AlreadyReported}!Input {
return .{ .object = openObject(io, path, false, false) catch |err| {
return diags.failParse(path, "failed to open {f}: {s}", .{ path, @errorName(err) });
} };
}
-pub fn openArchiveInput(io: Io, diags: *Diags, path: Path, must_link: bool, hidden: bool) error{LinkFailure}!Input {
+pub fn openArchiveInput(io: Io, diags: *Diags, path: Path, must_link: bool, hidden: bool) error{AlreadyReported}!Input {
return .{ .archive = openObject(io, path, must_link, hidden) catch |err| {
return diags.failParse(path, "failed to open {f}: {s}", .{ path, @errorName(err) });
} };
}
-pub fn openDsoInput(io: Io, diags: *Diags, path: Path, needed: bool, weak: bool, reexport: bool) error{LinkFailure}!Input {
+pub fn openDsoInput(io: Io, diags: *Diags, path: Path, needed: bool, weak: bool, reexport: bool) error{AlreadyReported}!Input {
return .{ .dso = openDso(io, path, needed, weak, reexport) catch |err| {
return diags.failParse(path, "failed to open {f}: {s}", .{ path, @errorName(err) });
} };
diff --git a/src/link/C.zig b/src/link/C.zig
@@ -474,7 +474,7 @@ pub fn updateContainerType(
pt: Zcu.PerThread,
ty: InternPool.Index,
success: bool,
-) link.File.UpdateContainerTypeError!void {
+) link.Error!void {
try c.type_pool.updateContainerType(pt, .{ .c = c }, ty, success);
}
@@ -570,7 +570,6 @@ pub fn updateNav(
.arena = arena.allocator(),
.pt = pt,
.mod = zcu.navFileScope(nav_index).mod.?,
- .error_msg = null,
.owner_nav = nav_index.toOptional(),
.is_naked_fn = false,
.expected_block = null,
@@ -588,10 +587,7 @@ pub fn updateNav(
defer c.string_bytes = aw.toArrayList();
const start = aw.written().len;
codegen.genDeclFwd(&dg, &aw.writer) catch |err| switch (err) {
- error.AnalysisFail => switch (zcu.codegenFailMsg(nav_index, dg.error_msg.?)) {
- error.CodegenFail => return,
- error.OutOfMemory => |e| return e,
- },
+ error.AlreadyReported => return,
error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
};
break :fwd_decl .{
@@ -605,10 +601,7 @@ pub fn updateNav(
defer c.string_bytes = aw.toArrayList();
const start = aw.written().len;
codegen.genDecl(&dg, &aw.writer) catch |err| switch (err) {
- error.AnalysisFail => switch (zcu.codegenFailMsg(nav_index, dg.error_msg.?)) {
- error.CodegenFail => return,
- error.OutOfMemory => |e| return e,
- },
+ error.AlreadyReported => return,
error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
};
break :code .{
@@ -661,7 +654,6 @@ fn updateUav(
.arena = arena.allocator(),
.pt = pt,
.mod = pt.zcu.root_mod,
- .error_msg = null,
.owner_nav = .none,
.is_naked_fn = false,
.expected_block = null,
@@ -683,9 +675,7 @@ fn updateUav(
.@"threadlocal" = false,
.init_val = val,
}) catch |err| switch (err) {
- error.AnalysisFail => {
- @panic("TODO: CBE error.AnalysisFail on uav");
- },
+ error.AlreadyReported => return,
error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
};
break :fwd_decl .{
@@ -704,9 +694,7 @@ fn updateUav(
.@"threadlocal" = false,
.init_val = val,
}) catch |err| switch (err) {
- error.AnalysisFail => {
- @panic("TODO: CBE error.AnalysisFail on uav");
- },
+ error.AlreadyReported => return,
error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
};
break :code .{
@@ -726,7 +714,7 @@ pub fn updateLineNumber(c: *C, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.
_ = ti_id;
}
-pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
+pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.Error!void {
const tracy = trace(@src());
defer tracy.end();
@@ -1112,7 +1100,6 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
.owner_nav = .none,
.is_naked_fn = false,
.expected_block = null,
- .error_msg = null,
.ctype_deps = .empty,
.uavs = .empty,
};
@@ -1156,14 +1143,14 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
codegen.genLazyCallModifierFn(&lazy_dg, fn_nav, .never_tail, &lazy_decls_aw.writer) catch |err| switch (err) {
error.WriteFailed => return error.OutOfMemory,
error.OutOfMemory => |e| return e,
- error.AnalysisFail => unreachable,
+ error.AlreadyReported => unreachable,
};
}
for (need_never_inline_funcs.keys()) |fn_nav| {
codegen.genLazyCallModifierFn(&lazy_dg, fn_nav, .never_inline, &lazy_decls_aw.writer) catch |err| switch (err) {
error.WriteFailed => return error.OutOfMemory,
error.OutOfMemory => |e| return e,
- error.AnalysisFail => unreachable,
+ error.AlreadyReported => unreachable,
};
}
}
@@ -1256,7 +1243,6 @@ pub fn updateExports(
.owner_nav = .none,
.is_naked_fn = false,
.expected_block = null,
- .error_msg = null,
.ctype_deps = .empty,
.uavs = .empty,
};
diff --git a/src/link/Coff.zig b/src/link/Coff.zig
@@ -43,7 +43,6 @@ lazy: std.EnumArray(link.File.LazySymbol.Kind, struct {
}),
pending_uavs: std.AutoArrayHashMapUnmanaged(Node.UavMapIndex, struct {
alignment: InternPool.Alignment,
- src_loc: Zcu.LazySrcLoc,
}),
relocs: std.ArrayList(Reloc),
const_prog_node: std.Progress.Node,
@@ -1532,11 +1531,8 @@ pub fn prelink(coff: *Coff, prog_node: std.Progress.Node) void {
pub fn updateNav(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {
coff.updateNavInner(pt, nav_index) catch |err| switch (err) {
- error.OutOfMemory,
- error.Overflow,
- error.RelocationNotByteAligned,
- => |e| return e,
- else => |e| return coff.base.cgFail(nav_index, "linker failed to update variable: {t}", .{e}),
+ else => |e| return e,
+ error.MappedFileIo => return coff.base.cgFail(nav_index, "linker failed to update variable: {t}", .{coff.mf.io_err.?}),
};
}
fn 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
codegen.generateSymbol(
&coff.base,
pt,
- zcu.navSrcLoc(nav_index),
.fromInterned(nav.resolved.?.value),
&nw.interface,
.{ .atom_index = @enumFromInt(@intFromEnum(si)) },
) catch |err| switch (err) {
- error.WriteFailed => return error.OutOfMemory,
+ error.WriteFailed => return nw.err.?,
else => |e| return e,
};
si.get(coff).size = @intCast(nw.interface.end);
@@ -1615,8 +1610,7 @@ pub fn lowerUav(
pt: Zcu.PerThread,
uav_val: InternPool.Index,
uav_align: InternPool.Alignment,
- src_loc: Zcu.LazySrcLoc,
-) !codegen.SymbolResult {
+) !link.File.SymbolId {
const zcu = pt.zcu;
const gpa = zcu.gpa;
@@ -1633,12 +1627,11 @@ pub fn lowerUav(
} else {
gop.value_ptr.* = .{
.alignment = uav_align,
- .src_loc = src_loc,
};
coff.const_prog_node.increaseEstimatedTotalItems(1);
}
}
- return .{ .sym_index = @enumFromInt(@intFromEnum(si)) };
+ return @enumFromInt(@intFromEnum(si));
}
pub fn updateFunc(
@@ -1648,15 +1641,11 @@ pub fn updateFunc(
mir: *const codegen.AnyMir,
) !void {
coff.updateFuncInner(pt, func_index, mir) catch |err| switch (err) {
- error.OutOfMemory,
- error.Overflow,
- error.RelocationNotByteAligned,
- error.CodegenFail,
- => |e| return e,
- else => |e| return coff.base.cgFail(
+ else => |e| return e,
+ error.MappedFileIo => return coff.base.cgFail(
pt.zcu.funcInfo(func_index).owner_nav,
- "linker failed to update function: {s}",
- .{@errorName(e)},
+ "linker failed to update function: {t}",
+ .{coff.mf.io_err.?},
),
};
}
@@ -1714,7 +1703,6 @@ fn updateFuncInner(
codegen.emitFunction(
&coff.base,
pt,
- zcu.navSrcLoc(func.owner_nav),
func_index,
@enumFromInt(@intFromEnum(si)),
mir,
@@ -1733,9 +1721,11 @@ pub fn updateErrorData(coff: *Coff, pt: Zcu.PerThread) !void {
.kind = .const_data,
.index = @intCast(coff.lazy.getPtr(.const_data).map.getIndex(.anyerror_type) orelse return),
}) catch |err| switch (err) {
- error.OutOfMemory => |e| return e,
- error.CodegenFail => return error.LinkFailure,
- else => |e| return coff.base.comp.link_diags.fail("updateErrorData failed {t}", .{e}),
+ else => |e| return e,
+ error.MappedFileIo => return coff.base.comp.link_diags.fail(
+ "updateErrorData failed: {t}",
+ .{coff.mf.io_err.?},
+ ),
};
}
@@ -1780,12 +1770,11 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
.{ .zcu = comp.zcu.?, .tid = tid },
pending_uav.key,
pending_uav.value.alignment,
- pending_uav.value.src_loc,
) catch |err| switch (err) {
- error.OutOfMemory => |e| return e,
- else => |e| return comp.link_diags.fail(
+ else => |e| return e,
+ error.MappedFileIo => return comp.link_diags.fail(
"linker failed to lower constant: {t}",
- .{e},
+ .{coff.mf.io_err.?},
),
};
break :task;
@@ -1800,10 +1789,10 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
);
defer sub_prog_node.end();
coff.flushGlobal(pt, gmi) catch |err| switch (err) {
- error.OutOfMemory => |e| return e,
- else => |e| return comp.link_diags.fail(
+ else => |e| return e,
+ error.MappedFileIo => return comp.link_diags.fail(
"linker failed to lower constant: {t}",
- .{e},
+ .{coff.mf.io_err.?},
),
};
break :task;
@@ -1827,10 +1816,10 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
);
defer sub_prog_node.end();
coff.flushLazy(pt, lmr) catch |err| switch (err) {
- error.OutOfMemory => |e| return e,
- else => |e| return comp.link_diags.fail(
+ else => |e| return e,
+ error.MappedFileIo => return comp.link_diags.fail(
"linker failed to lower lazy {s}: {t}",
- .{ kind, e },
+ .{ kind, coff.mf.io_err.? },
),
};
break :task;
@@ -1885,7 +1874,6 @@ fn flushUav(
pt: Zcu.PerThread,
umi: Node.UavMapIndex,
uav_align: InternPool.Alignment,
- src_loc: Zcu.LazySrcLoc,
) !void {
const zcu = pt.zcu;
const gpa = zcu.gpa;
@@ -1928,12 +1916,11 @@ fn flushUav(
codegen.generateSymbol(
&coff.base,
pt,
- src_loc,
.fromInterned(uav_val),
&nw.interface,
.{ .atom_index = @enumFromInt(@intFromEnum(si)) },
) catch |err| switch (err) {
- error.WriteFailed => return error.OutOfMemory,
+ error.WriteFailed => return nw.err.?,
else => |e| return e,
};
si.get(coff).size = @intCast(nw.interface.end);
@@ -2139,16 +2126,18 @@ fn flushLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {
var nw: MappedFile.Node.Writer = undefined;
ni.writer(&coff.mf, gpa, &nw);
defer nw.deinit();
- try codegen.generateLazySymbol(
+ codegen.generateLazySymbol(
&coff.base,
pt,
- Type.fromInterned(lazy.ty).srcLocOrNull(pt.zcu) orelse .unneeded,
lazy,
&required_alignment,
&nw.interface,
.none,
.{ .atom_index = @enumFromInt(@intFromEnum(si)) },
- );
+ ) catch |err| switch (err) {
+ error.WriteFailed => return nw.err.?,
+ else => |e| return e,
+ };
si.get(coff).size = @intCast(nw.interface.end);
si.applyLocationRelocs(coff);
}
@@ -2315,17 +2304,6 @@ pub fn updateExports(
exported: Zcu.Exported,
export_indices: []const Zcu.Export.Index,
) !void {
- return coff.updateExportsInner(pt, exported, export_indices) catch |err| switch (err) {
- error.OutOfMemory => error.OutOfMemory,
- error.LinkFailure => error.AnalysisFail,
- };
-}
-fn updateExportsInner(
- coff: *Coff,
- pt: Zcu.PerThread,
- exported: Zcu.Exported,
- export_indices: []const Zcu.Export.Index,
-) !void {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const ip = &zcu.intern_pool;
@@ -2340,18 +2318,11 @@ fn updateExportsInner(
try coff.symbol_table.ensureUnusedCapacity(gpa, export_indices.len);
const exported_si: Symbol.Index = switch (exported) {
.nav => |nav| try coff.navSymbol(zcu, nav),
- .uav => |uav| @enumFromInt(@intFromEnum(switch (try coff.lowerUav(
+ .uav => |uav| @enumFromInt(@intFromEnum(try coff.lowerUav(
pt,
uav,
Type.fromInterned(ip.typeOf(uav)).abiAlignment(zcu),
- export_indices[0].ptr(zcu).src,
- )) {
- .sym_index => |si| si,
- .fail => |em| {
- defer em.destroy(gpa);
- return coff.base.comp.link_diags.fail("{s}", .{em.msg});
- },
- })),
+ ))),
};
while (try coff.idle(pt.tid)) {}
const exported_ni = exported_si.node(coff);
diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig
@@ -51,21 +51,15 @@ pub const UpdateError = error{
Underflow,
UnexpectedEndOfFile,
NonResizable,
- /// TODO why is this in the error set?
- ConnectionResetByPeer,
- /// TODO why is this in the error set?
- SocketUnconnected,
+ Overflow,
} ||
- codegen.GenerateSymbolError ||
+ link.Error ||
Io.File.OpenError ||
Io.File.LengthError ||
Io.File.ReadPositionalError ||
Io.File.WritePositionalError;
-pub const FlushError = UpdateError;
-
-pub const RelocError =
- Io.File.PWriteError;
+pub const RelocError = Io.File.PWriteError;
pub const AddressSize = enum(u8) {
@"32" = 4,
@@ -1579,19 +1573,17 @@ pub const WipNav = struct {
pub const LocalConstTag = enum { comptime_arg, local_const };
pub fn genLocalConstDebugInfo(
wip_nav: *WipNav,
- src_loc: Zcu.LazySrcLoc,
tag: LocalConstTag,
opt_name: ?[]const u8,
val: Value,
) UpdateError!void {
- return wip_nav.genLocalConstDebugInfoWriterError(src_loc, tag, opt_name, val) catch |err| switch (err) {
+ return wip_nav.genLocalConstDebugInfoWriterError(tag, opt_name, val) catch |err| switch (err) {
error.WriteFailed => error.OutOfMemory,
else => |e| e,
};
}
fn genLocalConstDebugInfoWriterError(
wip_nav: *WipNav,
- src_loc: Zcu.LazySrcLoc,
tag: LocalConstTag,
opt_name: ?[]const u8,
val: Value,
@@ -1617,7 +1609,7 @@ pub const WipNav = struct {
});
if (opt_name) |name| try wip_nav.strp(name);
try wip_nav.refType(ty);
- if (has_runtime_bits) try wip_nav.blockValue(src_loc, val);
+ if (has_runtime_bits) try wip_nav.blockValue(val);
if (has_comptime_state) try wip_nav.refValue(val);
wip_nav.any_children = true;
}
@@ -2106,7 +2098,6 @@ pub const WipNav = struct {
fn blockValue(
wip_nav: *WipNav,
- src_loc: Zcu.LazySrcLoc,
val: Value,
) (UpdateError || Writer.Error)!void {
const ty = val.typeOf(wip_nav.pt.zcu);
@@ -2118,7 +2109,6 @@ pub const WipNav = struct {
try codegen.generateSymbol(
wip_nav.dwarf.bin_file,
wip_nav.pt,
- src_loc,
val,
&wip_nav.debug_info.writer,
.{ .debug_output = .{ .dwarf = wip_nav } },
@@ -2592,7 +2582,7 @@ pub fn initWipNav(
pt: Zcu.PerThread,
nav_index: InternPool.Nav.Index,
sym_index: link.File.SymbolId,
-) error{ OutOfMemory, CodegenFail }!WipNav {
+) error{ OutOfMemory, AlreadyReported }!WipNav {
return initWipNavInner(dwarf, pt, nav_index, sym_index) catch |err| switch (err) {
error.OutOfMemory => error.OutOfMemory,
else => |e| pt.zcu.codegenFail(nav_index, "failed to init dwarf: {s}", .{@errorName(e)}),
@@ -3017,7 +3007,7 @@ fn finishWipNavWriterError(
try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf });
}
-pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error{ OutOfMemory, CodegenFail }!void {
+pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error{ OutOfMemory, AlreadyReported }!void {
return updateComptimeNavInner(dwarf, pt, nav_index) catch |err| switch (err) {
error.OutOfMemory => error.OutOfMemory,
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
fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
- const nav_src_loc = zcu.navSrcLoc(nav_index);
const nav = ip.getNav(nav_index);
const inst_info = nav.srcInst(ip).resolveFull(ip).?;
@@ -3207,7 +3196,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
}.toSlice(ip));
const nav_ty = nav_val.typeOf(zcu);
try wip_nav.refType(nav_ty);
- try wip_nav.blockValue(nav_src_loc, nav_val);
+ try wip_nav.blockValue(nav_val);
try diw.writeUleb128(nav.resolved.?.@"align".toByteUnits() orelse
nav_ty.abiAlignment(zcu).toByteUnits().?);
try diw.writeByte(@intFromBool(decl.linkage != .normal));
@@ -3241,7 +3230,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
try diw.writeUleb128(nav.resolved.?.@"align".toByteUnits() orelse
nav_ty.abiAlignment(zcu).toByteUnits().?);
try diw.writeByte(@intFromBool(decl.linkage != .normal));
- if (has_runtime_bits) try wip_nav.blockValue(nav_src_loc, nav_val);
+ if (has_runtime_bits) try wip_nav.blockValue(nav_val);
if (has_comptime_state) try wip_nav.refValue(nav_val);
wip_nav.finishForward(nav_ty_reloc_index);
try wip_nav.abbrevCode(.is_const);
@@ -3551,19 +3540,6 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
};
defer wip_nav.deinit();
- // TODO: we really shouldn't need source locations at this point in the pipeline: we've lost
- // that information by now. If the linker fundamentally cannot lower certain values, that needs
- // to be caught in the frontend; if it can only hit transient failures, they should be reported
- // without trying to tie them to a bogus source location.
- const src_loc: Zcu.LazySrcLoc = .{
- .base_node_inst = inst: {
- const mod_root_file_index = zcu.module_roots.get(zcu.std_mod).?.unwrap().?;
- const mod_root_type_index = zcu.fileRootType(mod_root_file_index);
- break :inst ip.loadStructType(mod_root_type_index).zir_index;
- },
- .offset = .{ .byte_abs = 0 },
- };
-
const diw = &wip_nav.debug_info.writer;
var big_int_space: Value.BigIntSpace = undefined;
switch (value_ip_key) {
@@ -3588,7 +3564,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
else => if (ptr_type.sentinel == .none) .ptr_aligned_type else .ptr_aligned_sentinel_type,
});
try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
- if (ptr_type.sentinel != .none) try wip_nav.blockValue(src_loc, .fromInterned(ptr_type.sentinel));
+ if (ptr_type.sentinel != .none) try wip_nav.blockValue(.fromInterned(ptr_type.sentinel));
if (ptr_type.flags.alignment.toByteUnits()) |a| try diw.writeUleb128(a);
try diw.writeByte(@intFromEnum(ptr_type.flags.address_space));
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
const array_child_type: Type = .fromInterned(array_type.child);
try wip_nav.abbrevCode(if (array_type.sentinel == .none) .array_type else .array_sentinel_type);
try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
- if (array_type.sentinel != .none) try wip_nav.blockValue(src_loc, .fromInterned(array_type.sentinel));
+ if (array_type.sentinel != .none) try wip_nav.blockValue(.fromInterned(array_type.sentinel));
try wip_nav.refType(array_child_type);
try wip_nav.abbrevCode(.array_len);
try wip_nav.refType(.usize);
@@ -3880,7 +3856,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
if (has_comptime_state)
try wip_nav.refValue(.fromInterned(comptime_value))
else if (has_runtime_bits)
- try wip_nav.blockValue(src_loc, .fromInterned(comptime_value));
+ try wip_nav.blockValue(.fromInterned(comptime_value));
}
try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
},
@@ -3967,7 +3943,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
if (has_comptime_state)
try wip_nav.refValue(.fromInterned(field_init))
else if (has_runtime_bits)
- try wip_nav.blockValue(ty.srcLoc(zcu), .fromInterned(field_init));
+ try wip_nav.blockValue(.fromInterned(field_init));
}
try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
}
@@ -4332,7 +4308,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
if (has_comptime_state)
try wip_nav.refValue(.fromInterned(payload_val))
else
- try wip_nav.blockValue(src_loc, .fromInterned(payload_val));
+ try wip_nav.blockValue(.fromInterned(payload_val));
},
}
{
@@ -4500,7 +4476,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
{
try wip_nav.abbrevCode(.comptime_value_field_runtime_bits);
try wip_nav.strp("len");
- try wip_nav.blockValue(src_loc, .fromInterned(slice.len));
+ try wip_nav.blockValue(.fromInterned(slice.len));
}
try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
},
@@ -4513,8 +4489,8 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
try wip_nav.strp("has_value");
switch (optRepr(opt_child_type, zcu)) {
.opv_null => try diw.writeUleb128(0),
- .unpacked => try wip_nav.blockValue(src_loc, .makeBool(opt.val != .none)),
- .error_set, .pointer => try wip_nav.blockValue(src_loc, .fromInterned(value_index)),
+ .unpacked => try wip_nav.blockValue(.makeBool(opt.val != .none)),
+ .error_set, .pointer => try wip_nav.blockValue(.fromInterned(value_index)),
}
}
if (opt.val != .none) child_field: {
@@ -4530,7 +4506,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
if (has_comptime_state)
try wip_nav.refValue(.fromInterned(opt.val))
else
- try wip_nav.blockValue(src_loc, .fromInterned(opt.val));
+ try wip_nav.blockValue(.fromInterned(opt.val));
}
try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
},
@@ -4561,7 +4537,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
if (has_comptime_state)
try wip_nav.refValue(field_value)
else
- try wip_nav.blockValue(src_loc, field_value);
+ try wip_nav.blockValue(field_value);
}
},
.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
if (has_comptime_state)
try wip_nav.refValue(field_value)
else
- try wip_nav.blockValue(src_loc, field_value);
+ try wip_nav.blockValue(field_value);
},
inline .array_type, .vector_type => |sequence_type| {
const child_type: Type = .fromInterned(sequence_type.child);
@@ -4608,7 +4584,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
if (has_comptime_state)
try wip_nav.refValue(.fromInterned(elem))
else
- try wip_nav.blockValue(src_loc, .fromInterned(elem));
+ try wip_nav.blockValue(.fromInterned(elem));
}
},
else => unreachable,
@@ -4636,7 +4612,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
if (has_comptime_state)
try wip_nav.refValue(.fromInterned(un.val))
else
- try wip_nav.blockValue(src_loc, .fromInterned(un.val));
+ try wip_nav.blockValue(.fromInterned(un.val));
}
try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
},
@@ -4708,13 +4684,13 @@ fn refAbbrevCode(
return @intFromEnum(abbrev_code);
}
-pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
+pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) UpdateError!void {
return dwarf.flushWriterError(pt) catch |err| switch (err) {
error.WriteFailed => error.OutOfMemory,
else => |e| e,
};
}
-fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (FlushError || Writer.Error)!void {
+fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (UpdateError || Writer.Error)!void {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
const comp = dwarf.bin_file.comp;
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
@@ -476,9 +476,8 @@ pub fn lowerUav(
pt: Zcu.PerThread,
uav: InternPool.Index,
explicit_alignment: InternPool.Alignment,
- src_loc: Zcu.LazySrcLoc,
-) !codegen.SymbolResult {
- return self.zigObjectPtr().?.lowerUav(self, pt, uav, explicit_alignment, src_loc);
+) !link.File.SymbolId {
+ return self.zigObjectPtr().?.lowerUav(self, pt, uav, explicit_alignment);
}
pub 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 {
}
}
-pub fn flush(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
+pub fn flush(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.Error!void {
const tracy = trace(@src());
defer tracy.end();
@@ -757,7 +756,7 @@ pub fn flush(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std
defer sub_prog_node.end();
return flushInner(self, arena, tid) catch |err| switch (err) {
- error.OutOfMemory, error.LinkFailure => |e| return e,
+ error.OutOfMemory, error.AlreadyReported => |e| return e,
else => |e| return diags.fail("ELF flush failed: {t}", .{e}),
};
}
@@ -784,7 +783,7 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
.Exe => {},
}
- if (diags.hasErrors()) return error.LinkFailure;
+ if (diags.hasErrors()) return error.AlreadyReported;
// If we haven't already, create a linker-generated input file comprising of
// linker-defined synthetic symbols only such as `_DYNAMIC`, etc.
@@ -816,7 +815,7 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
}
self.checkDuplicates() catch |err| switch (err) {
- error.HasDuplicates => return error.LinkFailure,
+ error.HasDuplicates => return error.AlreadyReported,
else => |e| return e,
};
@@ -903,7 +902,7 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
error.RelocFailure, error.RelaxFailure => has_reloc_errors = true,
error.UnsupportedCpuArch => {
try self.reportUnsupportedCpuArch();
- return error.LinkFailure;
+ return error.AlreadyReported;
},
else => |e| return e,
};
@@ -912,7 +911,7 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
try self.reportUndefinedSymbols(&undefs);
- if (has_reloc_errors) return error.LinkFailure;
+ if (has_reloc_errors) return error.AlreadyReported;
}
try self.writePhdrTable();
@@ -921,10 +920,10 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
try self.writeMergeSections();
self.writeSyntheticSections() catch |err| switch (err) {
- error.RelocFailure => return error.LinkFailure,
+ error.RelocFailure => return error.AlreadyReported,
error.UnsupportedCpuArch => {
try self.reportUnsupportedCpuArch();
- return error.LinkFailure;
+ return error.AlreadyReported;
},
else => |e| return e,
};
@@ -938,7 +937,7 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
try self.writeElfHeader();
}
- if (diags.hasErrors()) return error.LinkFailure;
+ if (diags.hasErrors()) return error.AlreadyReported;
}
fn dumpArgvInit(self: *Elf, arena: Allocator) !void {
@@ -1053,7 +1052,7 @@ pub fn openParseObjectReportingFailure(self: *Elf, path: Path) void {
const diags = &comp.link_diags;
const obj = link.openObject(io, path, false, false) catch |err| {
switch (diags.failParse(path, "failed to open object: {t}", .{err})) {
- error.LinkFailure => return,
+ error.AlreadyReported => return,
}
};
self.parseObjectReportingFailure(obj);
@@ -1063,7 +1062,7 @@ fn parseObjectReportingFailure(self: *Elf, obj: link.Input.Object) void {
const comp = self.base.comp;
const diags = &comp.link_diags;
self.parseObject(obj) catch |err| switch (err) {
- error.LinkFailure => return, // already reported
+ error.AlreadyReported => return, // already reported
else => |e| diags.addParseError(obj.path, "failed to parse object: {t}", .{e}),
};
}
@@ -1343,7 +1342,7 @@ fn scanRelocs(self: *Elf) !void {
error.RelaxFailure => unreachable,
error.UnsupportedCpuArch => {
try self.reportUnsupportedCpuArch();
- return error.LinkFailure;
+ return error.AlreadyReported;
},
error.RelocFailure => has_reloc_errors = true,
else => |e| return e,
@@ -1354,7 +1353,7 @@ fn scanRelocs(self: *Elf) !void {
error.RelaxFailure => unreachable,
error.UnsupportedCpuArch => {
try self.reportUnsupportedCpuArch();
- return error.LinkFailure;
+ return error.AlreadyReported;
},
error.RelocFailure => has_reloc_errors = true,
else => |e| return e,
@@ -1363,7 +1362,7 @@ fn scanRelocs(self: *Elf) !void {
try self.reportUndefinedSymbols(&undefs);
- if (has_reloc_errors) return error.LinkFailure;
+ if (has_reloc_errors) return error.AlreadyReported;
if (self.zigObjectPtr()) |zo| {
try zo.asFile().createSymbolIndirection(self);
@@ -1690,7 +1689,7 @@ pub fn updateFunc(
pt: Zcu.PerThread,
func_index: InternPool.Index,
mir: *const codegen.AnyMir,
-) link.File.UpdateNavError!void {
+) link.Error!void {
return self.zigObjectPtr().?.updateFunc(self, pt, func_index, mir);
}
@@ -1698,7 +1697,7 @@ pub fn updateNav(
self: *Elf,
pt: Zcu.PerThread,
nav: InternPool.Nav.Index,
-) link.File.UpdateNavError!void {
+) link.Error!void {
return self.zigObjectPtr().?.updateNav(self, pt, nav);
}
@@ -1707,7 +1706,7 @@ pub fn updateContainerType(
pt: Zcu.PerThread,
ty: InternPool.Index,
success: bool,
-) link.File.UpdateContainerTypeError!void {
+) link.Error!void {
return self.zigObjectPtr().?.updateContainerType(pt, ty, success) catch |err| switch (err) {
error.OutOfMemory => |e| return e,
};
@@ -1718,11 +1717,11 @@ pub fn updateExports(
pt: Zcu.PerThread,
exported: Zcu.Exported,
export_indices: []const Zcu.Export.Index,
-) link.File.UpdateExportsError!void {
+) link.Error!void {
return self.zigObjectPtr().?.updateExports(self, pt, exported, export_indices);
}
-pub fn updateLineNumber(self: *Elf, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {
+pub fn updateLineNumber(self: *Elf, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) link.Error!void {
return self.zigObjectPtr().?.updateLineNumber(pt, ti_id);
}
@@ -1784,12 +1783,12 @@ pub fn resolveMergeSections(self: *Elf) !void {
if (!object.alive) continue;
if (!object.dirty) continue;
object.initInputMergeSections(self) catch |err| switch (err) {
- error.LinkFailure => has_errors = true,
+ error.AlreadyReported => has_errors = true,
else => |e| return e,
};
}
- if (has_errors) return error.LinkFailure;
+ if (has_errors) return error.AlreadyReported;
for (self.objects.items) |index| {
const object = self.file(index).?.object;
@@ -1803,12 +1802,12 @@ pub fn resolveMergeSections(self: *Elf) !void {
if (!object.alive) continue;
if (!object.dirty) continue;
object.resolveMergeSubsections(self) catch |err| switch (err) {
- error.LinkFailure => has_errors = true,
+ error.AlreadyReported => has_errors = true,
else => |e| return e,
};
}
- if (has_errors) return error.LinkFailure;
+ if (has_errors) return error.AlreadyReported;
}
pub fn finalizeMergeSections(self: *Elf) !void {
@@ -2998,7 +2997,7 @@ fn writeAtoms(self: *Elf) !void {
atom_list.write(&buffer, &undefs, self) catch |err| switch (err) {
error.UnsupportedCpuArch => {
try self.reportUnsupportedCpuArch();
- return error.LinkFailure;
+ return error.AlreadyReported;
},
error.RelocFailure, error.RelaxFailure => has_reloc_errors = true,
else => |e| return e,
@@ -3006,7 +3005,7 @@ fn writeAtoms(self: *Elf) !void {
}
try self.reportUndefinedSymbols(&undefs);
- if (has_reloc_errors) return error.LinkFailure;
+ if (has_reloc_errors) return error.AlreadyReported;
if (self.requiresThunks()) {
for (self.thunks.items) |th| {
@@ -3838,9 +3837,9 @@ pub fn failFile(
file_index: File.Index,
comptime format: []const u8,
args: anytype,
-) error{ OutOfMemory, LinkFailure } {
+) error{ OutOfMemory, AlreadyReported } {
try addFileError(self, file_index, format, args);
- return error.LinkFailure;
+ return error.AlreadyReported;
}
const FormatShdr = struct {
@@ -4409,7 +4408,7 @@ pub fn stringTableLookup(strtab: []const u8, off: u32) [:0]const u8 {
return slice[0..mem.indexOfScalar(u8, slice, 0).? :0];
}
-pub fn pwriteAll(elf_file: *Elf, bytes: []const u8, offset: u64) error{LinkFailure}!void {
+pub fn pwriteAll(elf_file: *Elf, bytes: []const u8, offset: u64) error{AlreadyReported}!void {
const comp = elf_file.base.comp;
const io = comp.io;
const diags = &comp.link_diags;
@@ -4417,7 +4416,7 @@ pub fn pwriteAll(elf_file: *Elf, bytes: []const u8, offset: u64) error{LinkFailu
return diags.fail("failed to write: {t}", .{err});
}
-pub fn setLength(elf_file: *Elf, length: u64) error{LinkFailure}!void {
+pub fn setLength(elf_file: *Elf, length: u64) error{AlreadyReported}!void {
const comp = elf_file.base.comp;
const io = comp.i;
const diags = &comp.link_diags;
@@ -4426,7 +4425,7 @@ pub fn setLength(elf_file: *Elf, length: u64) error{LinkFailure}!void {
};
}
-pub fn cast(elf_file: *Elf, comptime T: type, x: anytype) error{LinkFailure}!T {
+pub fn cast(elf_file: *Elf, comptime T: type, x: anytype) error{AlreadyReported}!T {
return std.math.cast(T, x) orelse {
const comp = elf_file.base.comp;
const diags = &comp.link_diags;
diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig
@@ -282,7 +282,7 @@ pub fn validateEFlags(
);
}
- if (any_errors) return error.LinkFailure;
+ if (any_errors) return error.AlreadyReported;
},
else => {},
}
@@ -829,7 +829,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void {
var err = try diags.addErrorWithNotes(1);
try err.addMsg("string not null terminated", .{});
err.addNote("in {f}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });
- return error.LinkFailure;
+ return error.AlreadyReported;
}
end += sh_entsize;
const string = data[start..end];
@@ -844,7 +844,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void {
var err = try diags.addErrorWithNotes(1);
try err.addMsg("size not a multiple of sh_entsize", .{});
err.addNote("in {f}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });
- return error.LinkFailure;
+ return error.AlreadyReported;
}
var pos: u32 = 0;
@@ -873,7 +873,7 @@ pub fn initOutputMergeSections(self: *Object, elf_file: *Elf) !void {
}
pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{
- LinkFailure,
+ AlreadyReported,
OutOfMemory,
/// TODO report the error and remove this
Overflow,
@@ -925,7 +925,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{
try err.addMsg("invalid symbol value: {x}", .{esym.st_value});
err.addNote("for symbol {s}", .{sym.name(elf_file)});
err.addNote("in {f}", .{self.fmtPath()});
- return error.LinkFailure;
+ return error.AlreadyReported;
};
sym.ref = .{ .index = res.msub_index, .file = imsec.merge_section_index };
@@ -950,7 +950,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{
var err = try diags.addErrorWithNotes(1);
try err.addMsg("invalid relocation at offset 0x{x}", .{rel.r_offset});
err.addNote("in {f}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });
- return error.LinkFailure;
+ return error.AlreadyReported;
};
const sym_index = try self.addSymbol(gpa);
diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig
@@ -272,24 +272,18 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void {
// Most lazy symbols can be updated on first use, but
// anyerror needs to wait for everything to be flushed.
- if (metadata.text_state != .unused) self.updateLazySymbol(
+ if (metadata.text_state != .unused) try self.updateLazySymbol(
elf_file,
pt,
.{ .kind = .code, .ty = .anyerror_type },
metadata.text_symbol_index,
- ) catch |err| switch (err) {
- error.CodegenFail => return error.LinkFailure,
- else => |e| return e,
- };
- if (metadata.rodata_state != .unused) self.updateLazySymbol(
+ );
+ if (metadata.rodata_state != .unused) try self.updateLazySymbol(
elf_file,
pt,
.{ .kind = .const_data, .ty = .anyerror_type },
metadata.rodata_symbol_index,
- ) catch |err| switch (err) {
- error.CodegenFail => return error.LinkFailure,
- else => |e| return e,
- };
+ );
}
for (self.lazy_syms.values()) |*metadata| {
if (metadata.text_state != .unused) metadata.text_state = .flushed;
@@ -999,8 +993,7 @@ pub fn lowerUav(
pt: Zcu.PerThread,
uav: InternPool.Index,
explicit_alignment: InternPool.Alignment,
- src_loc: Zcu.LazySrcLoc,
-) !codegen.SymbolResult {
+) !link.File.SymbolId {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const val = Value.fromInterned(uav);
@@ -1013,7 +1006,7 @@ pub fn lowerUav(
const sym = self.symbol(metadata.symbol_index);
const existing_alignment = sym.atom(elf_file).?.alignment;
if (uav_alignment.order(existing_alignment).compare(.lte))
- return .{ .sym_index = @enumFromInt(metadata.symbol_index) };
+ return @enumFromInt(metadata.symbol_index);
}
const osec = if (self.data_relro_index) |sym_index|
@@ -1033,31 +1026,25 @@ pub fn lowerUav(
const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{
@intFromEnum(uav),
}) catch unreachable;
- const res = self.lowerConst(
+ const sym_index = self.lowerConst(
elf_file,
pt,
name,
val,
uav_alignment,
osec,
- src_loc,
) catch |err| switch (err) {
error.OutOfMemory => |e| return e,
- else => |e| return .{ .fail = try Zcu.ErrorMsg.create(
- gpa,
- src_loc,
- "unable to lower constant value: {s}",
- .{@errorName(e)},
- ) },
+ else => |e| return elf_file.base.comp.link_diags.fail(
+ "failed to lower constant value: {t}",
+ .{e},
+ ),
};
- switch (res) {
- .sym_index => |sym_index| try self.uavs.put(gpa, uav, .{
- .symbol_index = @intFromEnum(sym_index),
- .allocated = true,
- }),
- .fail => {},
- }
- return res;
+ try self.uavs.put(gpa, uav, .{
+ .symbol_index = @intFromEnum(sym_index),
+ .allocated = true,
+ });
+ return sym_index;
}
pub fn getOrCreateMetadataForLazySymbol(
@@ -1370,7 +1357,7 @@ fn updateNavCode(
shdr_index: u32,
code: []const u8,
stt_bits: u8,
-) link.File.UpdateNavError!void {
+) link.Error!void {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const comp = elf_file.base.comp;
@@ -1473,7 +1460,7 @@ fn updateTlv(
sym_index: Symbol.Index,
shndx: u32,
code: []const u8,
-) link.File.UpdateNavError!void {
+) link.Error!void {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
const gpa = zcu.gpa;
@@ -1531,7 +1518,7 @@ pub fn updateFunc(
pt: Zcu.PerThread,
func_index: InternPool.Index,
mir: *const codegen.AnyMir,
-) link.File.UpdateNavError!void {
+) link.Error!void {
const tracy = trace(@src());
defer tracy.end();
@@ -1558,7 +1545,6 @@ pub fn updateFunc(
codegen.emitFunction(
&elf_file.base,
pt,
- zcu.navSrcLoc(func.owner_nav),
func_index,
@enumFromInt(sym_index),
mir,
@@ -1645,7 +1631,7 @@ pub fn updateNav(
elf_file: *Elf,
pt: Zcu.PerThread,
nav_index: InternPool.Nav.Index,
-) link.File.UpdateNavError!void {
+) link.Error!void {
const tracy = trace(@src());
defer tracy.end();
@@ -1670,7 +1656,7 @@ pub fn updateNav(
var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, @enumFromInt(sym_index));
defer debug_wip_nav.deinit();
dwarf.finishWipNav(pt, nav_index, &debug_wip_nav) catch |err| switch (err) {
- error.OutOfMemory, error.Overflow => |e| return e,
+ error.OutOfMemory, error.Canceled, error.AlreadyReported => |e| return e,
else => |e| return elf_file.base.cgFail(nav_index, "failed to finish dwarf nav: {s}", .{@errorName(e)}),
};
}
@@ -1691,7 +1677,6 @@ pub fn updateNav(
codegen.generateSymbol(
&elf_file.base,
pt,
- zcu.navSrcLoc(nav_index),
.fromInterned(nav.resolved.?.value),
&aw.writer,
.{ .atom_index = @enumFromInt(sym_index) },
@@ -1713,7 +1698,7 @@ pub fn updateNav(
try self.updateNavCode(elf_file, pt, nav_index, sym_index, shndx, code, elf.STT_OBJECT);
if (debug_wip_nav) |*wip_nav| self.dwarf.?.finishWipNav(pt, nav_index, wip_nav) catch |err| switch (err) {
- error.OutOfMemory, error.Overflow => |e| return e,
+ error.OutOfMemory, error.Canceled, error.AlreadyReported => |e| return e,
else => |e| return elf_file.base.cgFail(nav_index, "failed to finish dwarf nav: {s}", .{@errorName(e)}),
};
} else if (self.dwarf) |*dwarf| try dwarf.updateComptimeNav(pt, nav_index);
@@ -1759,7 +1744,6 @@ fn updateLazySymbol(
codegen.generateLazySymbol(
&elf_file.base,
pt,
- Type.fromInterned(sym.ty).srcLocOrNull(zcu) orelse .unneeded,
sym,
&required_alignment,
&aw.writer,
@@ -1827,8 +1811,7 @@ fn lowerConst(
val: Value,
required_alignment: InternPool.Alignment,
output_section_index: u32,
- src_loc: Zcu.LazySrcLoc,
-) !codegen.SymbolResult {
+) !link.File.SymbolId {
const gpa = pt.zcu.gpa;
var aw: std.Io.Writer.Allocating = .init(gpa);
@@ -1840,7 +1823,6 @@ fn lowerConst(
codegen.generateSymbol(
&elf_file.base,
pt,
- src_loc,
val,
&aw.writer,
.{ .atom_index = @enumFromInt(sym_index) },
@@ -1865,7 +1847,7 @@ fn lowerConst(
try elf_file.pwriteAll(code, atom_ptr.offset(elf_file));
- return .{ .sym_index = @enumFromInt(sym_index) };
+ return @enumFromInt(sym_index);
}
pub fn updateExports(
@@ -1874,7 +1856,7 @@ pub fn updateExports(
pt: Zcu.PerThread,
exported: Zcu.Exported,
export_indices: []const Zcu.Export.Index,
-) link.File.UpdateExportsError!void {
+) link.Error!void {
const tracy = trace(@src());
defer tracy.end();
@@ -1886,18 +1868,7 @@ pub fn updateExports(
break :blk self.navs.getPtr(nav).?;
},
.uav => |uav| self.uavs.getPtr(uav) orelse blk: {
- const first_exp = export_indices[0].ptr(zcu);
- const res = try self.lowerUav(elf_file, pt, uav, .none, first_exp.src);
- switch (res) {
- .sym_index => {},
- .fail => |em| {
- // TODO maybe it's enough to return an error here and let Zcu.processExportsInner
- // handle the error?
- try zcu.failed_exports.ensureUnusedCapacity(zcu.gpa, 1);
- zcu.failed_exports.putAssumeCapacityNoClobber(export_indices[0], em);
- return;
- },
- }
+ _ = try self.lowerUav(elf_file, pt, uav, .none);
break :blk self.uavs.getPtr(uav).?;
},
};
@@ -1962,12 +1933,12 @@ pub fn updateExports(
}
}
-pub fn updateLineNumber(self: *ZigObject, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {
+pub fn updateLineNumber(self: *ZigObject, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) link.Error!void {
if (self.dwarf) |*dwarf| {
const comp = dwarf.bin_file.comp;
const diags = &comp.link_diags;
dwarf.updateLineNumber(pt.zcu, ti_id) catch |err| switch (err) {
- error.Overflow, error.OutOfMemory => |e| return e,
+ error.OutOfMemory, error.Canceled, error.AlreadyReported => |e| return e,
else => |e| return diags.fail("failed to update dwarf line numbers: {s}", .{@errorName(e)}),
};
}
diff --git a/src/link/Elf/relocatable.zig b/src/link/Elf/relocatable.zig
@@ -23,7 +23,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {
const io = comp.io;
const diags = &comp.link_diags;
- if (diags.hasErrors()) return error.LinkFailure;
+ if (diags.hasErrors()) return error.AlreadyReported;
// First, we flush relocatable object file generated with our backends.
if (elf_file.zigObjectPtr()) |zig_object| {
@@ -151,13 +151,13 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {
try elf_file.base.file.?.setLength(io, total_size);
try elf_file.base.file.?.writePositionalAll(io, writer.buffered(), 0);
- if (diags.hasErrors()) return error.LinkFailure;
+ if (diags.hasErrors()) return error.AlreadyReported;
}
pub fn flushObject(elf_file: *Elf, comp: *Compilation) !void {
const diags = &comp.link_diags;
- if (diags.hasErrors()) return error.LinkFailure;
+ if (diags.hasErrors()) return error.AlreadyReported;
// Now, we are ready to resolve the symbols across all input files.
// 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 {
try elf_file.writeShdrTable();
try elf_file.writeElfHeader();
- if (diags.hasErrors()) return error.LinkFailure;
+ if (diags.hasErrors()) return error.AlreadyReported;
}
fn claimUnresolved(elf_file: *Elf) void {
diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig
@@ -162,6 +162,8 @@ const_prog_node: std.Progress.Node,
synth_prog_node: std.Progress.Node,
input_prog_node: std.Progress.Node,
+const Error = link.Error || error{MappedFileIo};
+
const Node = union(enum) {
file,
ehdr,
@@ -478,7 +480,7 @@ const Section = struct {
};
}
- fn rename(shndx: Index, elf: *Elf, new_name: []const u8) !void {
+ fn rename(shndx: Index, elf: *Elf, new_name: []const u8) Error!void {
const shstrtab_entry = try elf.string(.shstrtab, new_name);
switch (elf.shdrPtr(shndx)) {
inline else => |shdr| elf.targetStore(&shdr.name, @intFromEnum(shstrtab_entry)),
@@ -487,7 +489,7 @@ const Section = struct {
/// Asserts that `shndx` is a `SHT_RELA` section and ensures that its node has enough unused
/// space to hold `n` additional `ElfN.Rela` entries.
- fn relaEnsureAdditionalCapacity(rela_shndx: Index, elf: *Elf, n: usize) !void {
+ fn relaEnsureAdditionalCapacity(rela_shndx: Index, elf: *Elf, n: usize) Error!void {
const node = rela_shndx.get(elf).ni;
const need_size: u64 = switch (elf.shdrPtr(rela_shndx)) {
inline else => |shdr, class| need_size: {
@@ -509,11 +511,7 @@ const Section = struct {
break :need_size cur_size + need_additional * ent_size;
},
};
- _, const cur_node_size = node.location(&elf.mf).resolve(&elf.mf);
- if (need_size > cur_node_size) {
- const gpa = elf.base.comp.gpa;
- try node.resize(&elf.mf, gpa, need_size +| need_size / MappedFile.growth_factor);
- }
+ try elf.ensureNodeSize(node, need_size);
}
/// Asserts that `shndx` is a `SHT_RELA` section and deletes the `ElfN.Rela` entry at the
@@ -1192,7 +1190,7 @@ const SymbolReloc = struct {
}
};
-fn ensureUnusedSymbolCapacity(elf: *Elf, len: u32, kind: enum { all_local, maybe_global }) !void {
+fn ensureUnusedSymbolCapacity(elf: *Elf, len: u32, kind: enum { all_local, maybe_global }) Error!void {
const gpa = elf.base.comp.gpa;
try elf.symtab.ensureUnusedCapacity(gpa, len);
@@ -1210,11 +1208,7 @@ fn ensureUnusedSymbolCapacity(elf: *Elf, len: u32, kind: enum { all_local, maybe
const need_node_size: u64 = switch (elf.shdrPtr(.symtab)) {
inline else => |shdr, class| elf.targetLoad(&shdr.size) + len * @sizeOf(class.ElfN().Sym),
};
- _, const cur_node_size = Section.Index.symtab.get(elf).ni.location(&elf.mf).resolve(&elf.mf);
- if (cur_node_size < need_node_size) {
- const new_node_size = need_node_size +| need_node_size / MappedFile.growth_factor;
- try Section.Index.symtab.get(elf).ni.resize(&elf.mf, gpa, new_node_size);
- }
+ try elf.ensureNodeSize(Section.Index.symtab.get(elf).ni, need_node_size);
}
switch (kind) {
@@ -1232,18 +1226,14 @@ fn ensureUnusedSymbolCapacity(elf: *Elf, len: u32, kind: enum { all_local, maybe
const dynsym_need_size: u64 = switch (elf.shdrPtr(elf.shndx.dynsym)) {
inline else => |shdr, class| elf.targetLoad(&shdr.size) + len * @sizeOf(class.ElfN().Sym),
};
- _, const dynsym_cur_size = elf.shndx.dynsym.get(elf).ni.location(&elf.mf).resolve(&elf.mf);
- if (dynsym_cur_size < dynsym_need_size) {
- const new_size = dynsym_need_size +| dynsym_need_size / MappedFile.growth_factor;
- try elf.shndx.dynsym.get(elf).ni.resize(&elf.mf, gpa, new_size);
- }
+ try elf.ensureNodeSize(elf.shndx.dynsym.get(elf).ni, dynsym_need_size);
try elf.ensureUnusedPltCapacity(len);
}
},
}
}
-fn ensureUnusedPltCapacity(elf: *Elf, len: u32) !void {
+fn ensureUnusedPltCapacity(elf: *Elf, len: u32) Error!void {
const gpa = elf.base.comp.gpa;
try elf.shndx.rela_plt.relaEnsureAdditionalCapacity(elf, len);
@@ -1256,30 +1246,18 @@ fn ensureUnusedPltCapacity(elf: *Elf, len: u32) !void {
.X86_64 => {
// Ensure the `.plt` section's node is big enough
const plt_need_size: usize = 16 * (1 + need_plt_capacity);
- _, const plt_cur_size = elf.shndx.plt.get(elf).ni.location(&elf.mf).resolve(&elf.mf);
- if (plt_cur_size < plt_need_size) {
- const new_size = plt_need_size +| plt_need_size / MappedFile.growth_factor;
- try elf.shndx.plt.get(elf).ni.resize(&elf.mf, gpa, new_size);
- }
+ try elf.ensureNodeSize(elf.shndx.plt.get(elf).ni, plt_need_size);
// Ensure the `.got.plt` section's node is big enough
const got_plt_need_size: usize = switch (elf.identClass()) {
.NONE, _ => unreachable,
inline else => |class| @sizeOf(class.ElfN().Addr) * (3 + need_plt_capacity),
};
- _, const got_plt_cur_size = elf.shndx.got_plt.get(elf).ni.location(&elf.mf).resolve(&elf.mf);
- if (got_plt_cur_size < got_plt_need_size) {
- const new_size = got_plt_need_size +| got_plt_need_size / MappedFile.growth_factor;
- try elf.shndx.got_plt.get(elf).ni.resize(&elf.mf, gpa, new_size);
- }
+ try elf.ensureNodeSize(elf.shndx.got_plt.get(elf).ni, got_plt_need_size);
// Ensure the `.plt.sec` section's node is big enough
const plt_sec_need_size: usize = 16 * need_plt_capacity;
- _, const plt_sec_cur_size = elf.shndx.plt_sec.get(elf).ni.location(&elf.mf).resolve(&elf.mf);
- if (plt_sec_cur_size < plt_sec_need_size) {
- const new_size = plt_sec_need_size +| plt_sec_need_size / MappedFile.growth_factor;
- try elf.shndx.plt_sec.get(elf).ni.resize(&elf.mf, gpa, new_size);
- }
+ try elf.ensureNodeSize(elf.shndx.plt_sec.get(elf).ni, plt_sec_need_size);
},
}
}
@@ -1375,7 +1353,7 @@ const AddGlobalSymbolOptions = struct {
const Name = struct {
strtab: String(.strtab),
dynstr: String(.dynstr),
- fn string(elf: *Elf, slice: []const u8) !Name {
+ fn string(elf: *Elf, slice: []const u8) Error!Name {
return .{
.strtab = try elf.string(.strtab, slice),
.dynstr = switch (elf.shndx.dynsym) {
@@ -2205,7 +2183,14 @@ pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId {
const s: Symbol.Id = .local(lsi);
return s.toTypeErased();
}
-pub fn lazySymbol(elf: *Elf, lazy: link.File.LazySymbol) !link.File.SymbolId {
+pub fn lazySymbol(elf: *Elf, lazy: link.File.LazySymbol) link.Error!link.File.SymbolId {
+ const diags = &elf.base.comp.link_diags;
+ return elf.lazySymbolInner(lazy) catch |err| switch (err) {
+ error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
+ else => |e| return e,
+ };
+}
+fn lazySymbolInner(elf: *Elf, lazy: link.File.LazySymbol) Error!link.File.SymbolId {
const gpa = elf.base.comp.gpa;
try elf.ensureUnusedSymbolCapacity(1, .all_local);
@@ -2246,13 +2231,21 @@ pub fn lazySymbol(elf: *Elf, lazy: link.File.LazySymbol) !link.File.SymbolId {
const s: Symbol.Id = .local(gop.value_ptr.lsi);
return s.toTypeErased();
}
-pub fn externSymbol(elf: *Elf, opts: struct {
+pub const ExternSymbolOpts = struct {
name: []const u8,
lib_name: ?[]const u8,
type: std.elf.STT,
linkage: std.lang.GlobalLinkage = .strong,
visibility: std.lang.SymbolVisibility = .default,
-}) !link.File.SymbolId {
+};
+pub fn externSymbol(elf: *Elf, opts: ExternSymbolOpts) link.Error!link.File.SymbolId {
+ const diags = &elf.base.comp.link_diags;
+ return elf.externSymbolInner(opts) catch |err| switch (err) {
+ error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
+ else => |e| return e,
+ };
+}
+fn externSymbolInner(elf: *Elf, opts: ExternSymbolOpts) Error!link.File.SymbolId {
try elf.ensureUnusedSymbolCapacity(1, .maybe_global);
const symbol = elf.addGlobalSymbolAssumeCapacity(.{
.node = .none,
@@ -2265,7 +2258,7 @@ pub fn externSymbol(elf: *Elf, opts: struct {
.internal => @panic("TODO internal extern symbol"),
.strong => .strong,
.weak => .weak,
- .link_once => return error.LinkOnceUnsupported,
+ .link_once => return elf.base.comp.link_diags.fail("TODO(Elf2): link_once is not supported", .{}),
},
.visibility = switch (opts.visibility) {
.default => .DEFAULT,
@@ -2285,12 +2278,20 @@ pub fn addReloc(
target: link.File.SymbolId,
addend: i64,
@"type": MachineRelocType,
-) !void {
+) link.Error!void {
const node: MappedFile.Node.Index = Node.fromAtom(atom);
- try elf.ensureUnusedRelocCapacity(node, 1);
- try elf.addRelocAssumeCapacity(node, offset, .fromTypeErased(target), addend, @"type");
+ const diags = &elf.base.comp.link_diags;
+ elf.ensureUnusedRelocCapacity(node, 1) catch |err| switch (err) {
+ error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
+ else => |e| return e,
+ };
+ elf.addRelocAssumeCapacity(node, offset, .fromTypeErased(target), addend, @"type") catch |err| switch (err) {
+ error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
+ else => |e| return e,
+ };
}
-pub fn navSymbol(elf: *Elf, nav_index: InternPool.Nav.Index) !link.File.SymbolId {
+pub fn navSymbol(elf: *Elf, nav_index: InternPool.Nav.Index) link.Error!link.File.SymbolId {
+ const diags = &elf.base.comp.link_diags;
const zcu = elf.base.comp.zcu.?;
const ip = &zcu.intern_pool;
const nav = ip.getNav(nav_index);
@@ -2303,7 +2304,10 @@ pub fn navSymbol(elf: *Elf, nav_index: InternPool.Nav.Index) !link.File.SymbolId
.visibility = @"extern".visibility,
});
}
- const nmi = try elf.navMapIndex(zcu, nav_index);
+ const nmi = elf.navMapIndex(zcu, nav_index) catch |err| switch (err) {
+ error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
+ else => |e| return e,
+ };
const s: Symbol.Id = .local(nmi.symbol(elf));
return s.toTypeErased();
}
@@ -2311,8 +2315,12 @@ pub fn uavSymbol(
elf: *Elf,
uav_val: InternPool.Index,
uav_align: InternPool.Alignment,
-) !link.File.SymbolId {
- const umi = try elf.uavMapIndex(uav_val, uav_align);
+) link.Error!link.File.SymbolId {
+ const diags = &elf.base.comp.link_diags;
+ const umi = elf.uavMapIndex(uav_val, uav_align) catch |err| switch (err) {
+ error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
+ else => |e| return e,
+ };
const s: Symbol.Id = .local(umi.symbol(elf));
return s.toTypeErased();
}
@@ -2321,7 +2329,7 @@ pub fn getNavVAddr(
pt: Zcu.PerThread,
nav: InternPool.Nav.Index,
reloc_info: link.File.RelocInfo,
-) !u64 {
+) link.Error!u64 {
_ = pt;
return elf.getVAddr(reloc_info, try elf.navSymbol(nav));
}
@@ -2329,41 +2337,33 @@ pub fn getUavVAddr(
elf: *Elf,
uav_val: InternPool.Index,
reloc_info: link.File.RelocInfo,
-) !u64 {
+) link.Error!u64 {
return elf.getVAddr(reloc_info, try elf.uavSymbol(uav_val, .none));
}
-pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target: link.File.SymbolId) !u64 {
- const node: MappedFile.Node.Index = Node.fromAtom(reloc_info.parent.atom_index);
- const target_sym: Symbol.Id = .fromTypeErased(target);
- try elf.ensureUnusedRelocCapacity(node, 1);
- try elf.addRelocAssumeCapacity(
- node,
+pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target: link.File.SymbolId) link.Error!u64 {
+ try elf.addReloc(
+ reloc_info.parent.atom_index,
reloc_info.offset,
- target_sym,
+ target,
reloc_info.addend,
.absAddr(elf),
);
- return target_sym.value(elf);
+ return Symbol.Id.fromTypeErased(target).value(elf);
}
pub fn lowerUav(
elf: *Elf,
pt: Zcu.PerThread,
uav_val: InternPool.Index,
uav_align: InternPool.Alignment,
- src_loc: Zcu.LazySrcLoc,
-) !codegen.SymbolResult {
+) link.Error!link.File.SymbolId {
_ = pt;
+ const diags = &elf.base.comp.link_diags;
const umi = elf.uavMapIndex(uav_val, uav_align) catch |err| switch (err) {
- error.OutOfMemory => |e| return e,
- else => |e| return .{ .fail = try Zcu.ErrorMsg.create(
- elf.base.comp.gpa,
- src_loc,
- "linker failed to update constant: {s}",
- .{@errorName(e)},
- ) },
+ error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
+ else => |e| return e,
};
const s: Symbol.Id = .local(umi.symbol(elf));
- return .{ .sym_index = s.toTypeErased() };
+ return s.toTypeErased();
}
const StringSection = enum {
@@ -2390,7 +2390,7 @@ fn String(section: StringSection) type {
}
};
}
-fn string(elf: *Elf, comptime section: StringSection, key: []const u8) !String(section) {
+fn string(elf: *Elf, comptime section: StringSection, key: []const u8) Error!String(section) {
const st: *StringTable = &@field(elf, @tagName(section));
return @enumFromInt(try st.get(elf, section.shndx(elf), key));
}
@@ -2424,7 +2424,7 @@ const StringTable = struct {
}
};
- pub fn get(st: *StringTable, elf: *Elf, shndx: Section.Index, key: []const u8) !u32 {
+ pub fn get(st: *StringTable, elf: *Elf, shndx: Section.Index, key: []const u8) Error!u32 {
// If we are in `initHeaders` the strtab might not be initalized yet, so we need to special
// case the empty string.
if (key.len == 0) return 0;
@@ -2450,9 +2450,7 @@ const StringTable = struct {
if (shndx == elf.shndx.dynstr) {
elf.updateDynamicEntry(std.elf.DT_STRSZ, new_size);
}
- _, const node_size = ni.location(&elf.mf).resolve(&elf.mf);
- if (new_size > node_size)
- try ni.resize(&elf.mf, gpa, new_size +| new_size / MappedFile.growth_factor);
+ try elf.ensureNodeSize(ni, new_size);
const slice = ni.slice(&elf.mf)[old_size..];
@memcpy(slice[0..key.len], key);
slice[key.len] = 0;
@@ -3615,7 +3613,13 @@ fn mapInputSection(elf: *Elf, opts: struct {
flags: std.elf.SHF,
addralign: std.elf.Xword,
entsize: std.elf.Xword,
-}) !Section.Index {
+}) (Error || error{
+ UnsupportedSectionFlags,
+ TlsSectionUnavailable,
+ StripSection,
+ SectionFlagsConflict,
+ SectionTypeConflict,
+})!Section.Index {
const gpa = elf.base.comp.gpa;
if (opts.flags.INFO_LINK or
opts.flags.LINK_ORDER or
@@ -3733,7 +3737,7 @@ fn mapInputSection(elf: *Elf, opts: struct {
}
return existing_shndx;
}
-fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.NavMapIndex {
+fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node.NavMapIndex {
const gpa = zcu.gpa;
const ip = &zcu.intern_pool;
const nav = ip.getNav(nav_index);
@@ -3826,7 +3830,7 @@ fn uavMapIndex(
elf: *Elf,
uav_val: InternPool.Index,
uav_align: InternPool.Alignment,
-) !Node.UavMapIndex {
+) Error!Node.UavMapIndex {
const gpa = elf.base.comp.gpa;
const zcu = elf.base.comp.zcu.?;
@@ -3878,26 +3882,78 @@ fn uavMapIndex(
return umi;
}
-pub fn loadInput(elf: *Elf, input: link.Input) (Io.File.Reader.SizeError ||
- Io.File.Reader.Error || MappedFile.Error || error{ EndOfStream, BadMagic, LinkFailure })!void {
- const io = elf.base.comp.io;
+/// Internal error set used by input parsing functions `loadObject`, `loadArchive`, `loadDso`.
+const LoadParseInputError = Error || Io.File.SeekError || Io.Reader.Error;
+
+/// Returns `error.BadMagic` if a DSO or static archive has an incorrect magic number, which
+/// indicates to the frontend that the input could be a GNU ld script instead.
+pub fn loadInput(elf: *Elf, input: link.Input) (link.Error || error{BadMagic})!void {
+ const diags = &elf.base.comp.link_diags;
+ return elf.loadInputInner(input) catch |err| switch (err) {
+ else => |e| return e,
+ error.MappedFileIo => return diags.fail(
+ "failed to write output file: {t}",
+ .{elf.mf.io_err.?},
+ ),
+ };
+}
+fn loadInputInner(elf: *Elf, input: link.Input) (Error || error{BadMagic})!void {
+ const comp = elf.base.comp;
+ const diags = &comp.link_diags;
+ const io = comp.io;
var buf: [4096]u8 = undefined;
switch (input) {
.object => |object| {
var fr = object.file.reader(io, &buf);
elf.loadObject(object.path, null, &fr, .{
.offset = fr.logicalPos(),
- .size = try fr.getSize(),
+ .size = fr.getSize() catch |err| switch (err) {
+ error.Canceled => |e| return e,
+ else => |e| return diags.fail(
+ "failed to stat \"{f}\": {t}",
+ .{ object.path.fmtEscapeString(), e },
+ ),
+ },
}) catch |err| switch (err) {
- error.ReadFailed => return fr.err.?,
else => |e| return e,
+ error.EndOfStream => return diags.failParse(
+ object.path,
+ "unexpected eof",
+ .{},
+ ),
+ error.AccessDenied, error.Unexpected, error.Unseekable => |e| return diags.fail(
+ "failed to read \"{f}\": {t}",
+ .{ object.path.fmtEscapeString(), e },
+ ),
+ error.ReadFailed => switch (fr.err.?) {
+ error.Canceled => |e| return e,
+ else => |e| return diags.fail(
+ "failed to read \"{f}\": {t}",
+ .{ object.path.fmtEscapeString(), e },
+ ),
+ },
};
},
.archive => |archive| {
var fr = archive.file.reader(io, &buf);
elf.loadArchive(archive.path, &fr) catch |err| switch (err) {
- error.ReadFailed => return fr.err.?,
else => |e| return e,
+ error.EndOfStream => return diags.failParse(
+ archive.path,
+ "unexpected eof",
+ .{},
+ ),
+ error.AccessDenied, error.Unexpected, error.Unseekable => |e| return diags.fail(
+ "failed to read \"{f}\": {t}",
+ .{ archive.path.fmtEscapeString(), e },
+ ),
+ error.ReadFailed => switch (fr.err.?) {
+ error.Canceled => |e| return e,
+ else => |e| return diags.fail(
+ "failed to read \"{f}\": {t}",
+ .{ archive.path.fmtEscapeString(), e },
+ ),
+ },
};
},
.res => unreachable,
@@ -3905,8 +3961,23 @@ pub fn loadInput(elf: *Elf, input: link.Input) (Io.File.Reader.SizeError ||
try elf.needed.ensureUnusedCapacity(elf.base.comp.gpa, 1);
var fr = dso.file.reader(io, &buf);
elf.loadDso(dso.path, &fr) catch |err| switch (err) {
- error.ReadFailed => return fr.err.?,
else => |e| return e,
+ error.EndOfStream => return diags.failParse(
+ dso.path,
+ "unexpected eof",
+ .{},
+ ),
+ error.AccessDenied, error.Unexpected, error.Unseekable => |e| return diags.fail(
+ "failed to read \"{f}\": {t}",
+ .{ dso.path.fmtEscapeString(), e },
+ ),
+ error.ReadFailed => switch (fr.err.?) {
+ error.Canceled => |e| return e,
+ else => |e| return diags.fail(
+ "failed to read \"{f}\": {t}",
+ .{ dso.path.fmtEscapeString(), e },
+ ),
+ },
};
},
.dso_exact => |dso_exact| {
@@ -3919,14 +3990,22 @@ pub fn loadInput(elf: *Elf, input: link.Input) (Io.File.Reader.SizeError ||
},
}
}
-fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) !void {
+fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (LoadParseInputError || error{BadMagic})!void {
const comp = elf.base.comp;
const gpa = comp.gpa;
const diags = &comp.link_diags;
const r = &fr.interface;
log.debug("loadArchive({f})", .{path.fmtEscapeString()});
- if (!std.mem.eql(u8, try r.take(std.elf.ARMAG.len), std.elf.ARMAG)) return error.BadMagic;
+ {
+ const magic = r.take(std.elf.ARMAG.len) catch |err| switch (err) {
+ error.ReadFailed => |e| return e,
+ error.EndOfStream => return error.BadMagic,
+ };
+ if (!std.mem.eql(u8, magic, std.elf.ARMAG)) {
+ return error.BadMagic;
+ }
+ }
var strtab: std.Io.Writer.Allocating = .init(gpa);
defer strtab.deinit();
while (r.takeStruct(std.elf.ar_hdr, native_endian)) |header| {
@@ -3987,7 +4066,7 @@ fn loadObject(
member: ?[]const u8,
fr: *Io.File.Reader,
fl: MappedFile.Node.FileLocation,
-) !void {
+) LoadParseInputError!void {
const comp = elf.base.comp;
const gpa = comp.gpa;
const diags = &comp.link_diags;
@@ -3995,7 +4074,14 @@ fn loadObject(
const input_index: Node.InputIndex = @enumFromInt(elf.inputs.items.len);
log.debug("loadObject({f}{f})", .{ path.fmtEscapeString(), fmtMemberString(member) });
- try elf.checkInputIdent(path, r);
+ elf.checkInputIdent(path, r) catch |err| switch (err) {
+ else => |e| return e,
+ error.BadMagic => return diags.failParse(
+ path,
+ "bad ELF magic",
+ .{},
+ ),
+ };
try elf.ensureUnusedSymbolCapacity(1, .all_local);
try elf.inputs.ensureUnusedCapacity(gpa, 1);
const file_symbol = elf.addLocalSymbolAssumeCapacity(.{
@@ -4376,7 +4462,7 @@ fn loadObject(
},
}
}
-fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) !void {
+fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (LoadParseInputError || error{BadMagic})!void {
const comp = elf.base.comp;
const gpa = comp.gpa;
const diags = &comp.link_diags;
@@ -4593,23 +4679,29 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) !void {
/// Validates that the `std.elf.Ident` present at the start of `r` is a compatible link input.
///
-/// Returns an error if it is incompatible, or if the ident is broken or missing.
+/// Returns an error if it is incompatible, or if the ident is broken or missing---usually
+/// `error.AlreadyReported`, but if the magic number is missing or incorrect, returns
+/// `error.BadMagic` instead.
///
/// Does not advance the position of `r`. Requires `r` to have a 16-byte buffer.
fn checkInputIdent(
elf: *const Elf,
path: std.Build.Cache.Path,
r: *Io.Reader,
-) !void {
+) error{ BadMagic, EndOfStream, AlreadyReported, ReadFailed }!void {
const diags = &elf.base.comp.link_diags;
- const ident = try r.peekStructPointer(std.elf.Ident);
- const target: *const std.elf.Ident = @ptrCast(elf.mf.memory_map.memory[0..@sizeOf(std.elf.Ident)]);
-
- if (!std.mem.eql(u8, &ident.magic, std.elf.MAGIC)) {
+ const magic = r.peek(std.elf.MAGIC.len) catch |err| switch (err) {
+ error.ReadFailed => |e| return e,
+ error.EndOfStream => return error.BadMagic,
+ };
+ if (!std.mem.eql(u8, magic, std.elf.MAGIC)) {
return error.BadMagic;
}
+ const ident = try r.peekStructPointer(std.elf.Ident);
+ const target: *const std.elf.Ident = @ptrCast(elf.mf.memory_map.memory[0..@sizeOf(std.elf.Ident)]);
+
if (ident.class != target.class) return diags.failParse(
path,
"bad ELF class ({?s})",
@@ -4649,7 +4741,7 @@ fn createInitFiniArraySection(
shndx: *Section.Index,
comptime name: []const u8,
@"type": std.elf.SHT,
-) !void {
+) Error!void {
assert(shndx.* == .UNDEF);
const gpa = elf.base.comp.gpa;
const addr_align: std.mem.Alignment = switch (elf.identClass()) {
@@ -4722,14 +4814,15 @@ fn updateInitFiniArraySectionSize(
Symbol.Id.global(end_sym_name).flushMoved(elf, end_vaddr);
}
-pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) !void {
+pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) link.Error!void {
_ = prog_node;
+ const diags = &elf.base.comp.link_diags;
elf.prelinkInner() catch |err| switch (err) {
- error.OutOfMemory => |e| return e,
- else => |e| return elf.base.comp.link_diags.fail("prelink failed: {t}", .{e}),
+ error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
+ else => |e| return e,
};
}
-fn prelinkInner(elf: *Elf) !void {
+fn prelinkInner(elf: *Elf) Error!void {
const comp = elf.base.comp;
const gpa = comp.gpa;
try elf.ensureUnusedSymbolCapacity(1, .all_local);
@@ -4954,7 +5047,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
entsize: std.elf.Word = 0,
node_align: std.mem.Alignment = .@"1",
fixed: bool = false,
-}) !Section.Index {
+}) Error!Section.Index {
switch (opts.type) {
.NULL => assert(opts.size == 0),
.PROGBITS => assert(opts.size > 0),
@@ -4996,9 +5089,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
break :shndx .{ @enumFromInt(shndx), @as(u64, elf.targetLoad(&ehdr.shentsize)) * @as(u64, shnum) };
},
};
- _, const shdr_node_size = elf.ni.shdr.location(&elf.mf).resolve(&elf.mf);
- if (new_shdr_size > shdr_node_size)
- try elf.ni.shdr.resize(&elf.mf, gpa, new_shdr_size +| new_shdr_size / MappedFile.growth_factor);
+ try elf.ensureNodeSize(elf.ni.shdr, new_shdr_size);
const ni = try elf.mf.addLastChildNode(gpa, switch (elf.ehdrField(.type)) {
.NONE, .CORE, _ => unreachable,
.REL => elf.ni.file,
@@ -5045,7 +5136,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
return shndx;
}
-fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize) !void {
+fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize) Error!void {
if (len == 0) return;
const gpa = elf.base.comp.gpa;
try elf.symbol_relocs.ensureUnusedCapacity(gpa, len);
@@ -5090,14 +5181,11 @@ fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize)
try elf.tls_size_symbol_relocs.ensureUnusedCapacity(gpa, len);
const new_got_entries = len * 2; // at worst, every reloc is a new TLSGD
try elf.got.ensureUnusedCapacity(gpa, new_got_entries);
- const got_ni = elf.shndx.got.get(elf).ni;
- _, const got_node_size = got_ni.location(&elf.mf).resolve(&elf.mf);
const need_got_size = switch (class) {
.NONE, _ => unreachable,
inline else => |ct_class| (elf.got.count() + new_got_entries) * @sizeOf(ct_class.ElfN().Addr),
};
- if (need_got_size > got_node_size)
- try got_ni.resize(&elf.mf, gpa, need_got_size +| need_got_size / MappedFile.growth_factor);
+ try elf.ensureNodeSize(elf.shndx.got.get(elf).ni, need_got_size);
if (elf.shndx.dynamic != .UNDEF) {
try elf.shndx.rela_dyn.relaEnsureAdditionalCapacity(elf, new_got_entries);
@@ -5114,7 +5202,7 @@ fn addRelocAssumeCapacity(
target: Symbol.Id,
addend: i64,
@"type": MachineRelocType,
-) !void {
+) Error!void {
assert(node != .none);
switch (elf.ehdrField(.type)) {
.NONE, .CORE, _ => unreachable,
@@ -5233,7 +5321,7 @@ fn addSymbolRelocAssumeCapacity(
target: Symbol.Id,
addend: i64,
@"type": SymbolReloc.Type,
-) !void {
+) Error!void {
assert(elf.ehdrField(.type) != .REL);
const rela_index: Section.RelaIndex.Optional = r: {
@@ -5594,7 +5682,7 @@ fn nodeWantsDsoRelocation(elf: *Elf, node: MappedFile.Node.Index) enum { yes, ye
/// global where needed---the caller does not need to do this.
///
/// Asserts that `elf.shndx.dynamic != .UNDEF` and that `global_name` refers to an *undefined* global.
-fn maybeAddCopyRelocation(elf: *Elf, global_name: String(.strtab)) !bool {
+fn maybeAddCopyRelocation(elf: *Elf, global_name: String(.strtab)) Error!bool {
assert(elf.shndx.dynamic != .UNDEF);
const gpa = elf.base.comp.gpa;
@@ -5657,16 +5745,14 @@ fn maybeAddCopyRelocation(elf: *Elf, global_name: String(.strtab)) !bool {
return true;
}
-pub fn updateNav(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {
+pub fn updateNav(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) link.Error!void {
+ const diags = &elf.base.comp.link_diags;
elf.updateNavInner(pt, nav_index) catch |err| switch (err) {
- error.OutOfMemory,
- error.Overflow,
- error.RelocationNotByteAligned,
- => |e| return e,
- else => |e| return elf.base.cgFail(nav_index, "linker failed to update variable: {t}", .{e}),
+ error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
+ else => |e| return e,
};
}
-fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {
+fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) Error!void {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const ip = &zcu.intern_pool;
@@ -5689,12 +5775,11 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)
codegen.generateSymbol(
&elf.base,
pt,
- zcu.navSrcLoc(nav_index),
.fromInterned(nav.resolved.?.value),
&nw.interface,
.{ .atom_index = Node.toAtom(ni) },
) catch |err| switch (err) {
- error.WriteFailed => return error.OutOfMemory,
+ error.WriteFailed => return nw.err.?,
else => |e| return e,
};
switch (elf.symPtr(nmi.symbol(elf).index())) {
@@ -5707,18 +5792,11 @@ pub fn updateFunc(
pt: Zcu.PerThread,
func_index: InternPool.Index,
mir: *const codegen.AnyMir,
-) !void {
+) link.Error!void {
+ const diags = &elf.base.comp.link_diags;
elf.updateFuncInner(pt, func_index, mir) catch |err| switch (err) {
- error.OutOfMemory,
- error.Overflow,
- error.RelocationNotByteAligned,
- error.CodegenFail,
- => |e| return e,
- else => |e| return elf.base.cgFail(
- pt.zcu.funcInfo(func_index).owner_nav,
- "linker failed to update function: {s}",
- .{@errorName(e)},
- ),
+ error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
+ else => |e| return e,
};
}
fn updateFuncInner(
@@ -5726,7 +5804,7 @@ fn updateFuncInner(
pt: Zcu.PerThread,
func_index: InternPool.Index,
mir: *const codegen.AnyMir,
-) !void {
+) Error!void {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const ip = &zcu.intern_pool;
@@ -5748,7 +5826,6 @@ fn updateFuncInner(
codegen.emitFunction(
&elf.base,
pt,
- zcu.navSrcLoc(func.owner_nav),
func_index,
Node.toAtom(ni),
mir,
@@ -5763,14 +5840,14 @@ fn updateFuncInner(
}
}
-pub fn updateErrorData(elf: *Elf, pt: Zcu.PerThread) !void {
+pub fn updateErrorData(elf: *Elf, pt: Zcu.PerThread) link.Error!void {
+ const diags = &elf.base.comp.link_diags;
elf.flushLazy(pt, .{
.kind = .const_data,
.index = @intCast(elf.lazy.getPtr(.const_data).map.getIndex(.anyerror_type) orelse return),
}) catch |err| switch (err) {
- error.OutOfMemory => |e| return e,
- error.CodegenFail => return error.LinkFailure,
- else => |e| return elf.base.comp.link_diags.fail("updateErrorData failed: {t}", .{e}),
+ error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
+ else => |e| return e,
};
}
@@ -5779,8 +5856,9 @@ pub fn flush(
arena: std.mem.Allocator,
tid: Zcu.PerThread.Id,
prog_node: std.Progress.Node,
-) !void {
+) link.Error!void {
const comp = elf.base.comp;
+ const diags = &comp.link_diags;
_ = arena;
_ = prog_node;
@@ -5791,12 +5869,12 @@ pub fn flush(
any_undef = true;
comp.link_diags.addError("undefined global symbol '{s}'", .{name.slice(elf)});
}
- if (any_undef) return error.LinkFailure;
+ if (any_undef) return error.AlreadyReported;
}
elf.updateDynamicTextrel() catch |err| switch (err) {
- error.OutOfMemory => |e| return e,
- else => |e| return elf.base.comp.link_diags.fail("updateDynamicTextrel failed: {t}", .{e}),
+ error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
+ else => |e| return e,
};
while (try elf.idle(tid)) {}
@@ -5812,8 +5890,8 @@ pub fn flush(
.named => |named| named,
};
const sym_name_strtab = elf.string(.strtab, sym_name_slice) catch |err| switch (err) {
- error.Canceled => |e| return e,
- else => |e| return comp.link_diags.fail("flush write failed: {t}", .{e}),
+ error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
+ else => |e| return e,
};
if (elf.globalByName(sym_name_strtab) == null) break :entry 0;
break :entry Symbol.Id.global(sym_name_strtab).value(elf);
@@ -5823,11 +5901,11 @@ pub fn flush(
}
elf.mf.flush() catch |err| switch (err) {
- error.Canceled => |e| return e,
- else => |e| return comp.link_diags.fail("flush write failed: {t}", .{e}),
+ error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
+ else => |e| return e,
};
}
-fn updateDynamicTextrel(elf: *Elf) !void {
+fn updateDynamicTextrel(elf: *Elf) Error!void {
if (elf.shndx.dynamic == .UNDEF) return;
const dynamic_ni = elf.shndx.dynamic.get(elf).ni;
switch (elf.shdrPtr(elf.shndx.dynamic)) {
@@ -5844,10 +5922,7 @@ fn updateDynamicTextrel(elf: *Elf) !void {
if (!has_textrel) {
// Add a DT_TEXTREL entry before the final DT_NULL entry.
const new_size = cur_size + @sizeOf([2]class.ElfN().Addr);
- _, const node_size = dynamic_ni.location(&elf.mf).resolve(&elf.mf);
- if (node_size < new_size) {
- try dynamic_ni.resize(&elf.mf, elf.base.comp.gpa, new_size);
- }
+ try elf.ensureNodeSize(dynamic_ni, new_size);
elf.targetStore(&shdr.size, new_size);
const new_entries: [][2]class.ElfN().Addr = @ptrCast(@alignCast(
dynamic_ni.slice(&elf.mf)[0..@intCast(new_size)],
@@ -5869,18 +5944,16 @@ fn updateDynamicTextrel(elf: *Elf) !void {
}
}
-pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) !bool {
+pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {
const comp = elf.base.comp;
+ const diags = &comp.link_diags;
task: {
while (elf.pending_uavs.pop()) |umi| {
const sub_prog_node = elf.idleProgNode(tid, elf.const_prog_node, .{ .uav = umi });
defer sub_prog_node.end();
elf.flushUav(.{ .zcu = comp.zcu.?, .tid = tid }, umi) catch |err| switch (err) {
- error.OutOfMemory => |e| return e,
- else => |e| return comp.link_diags.fail(
- "linker failed to lower constant: {t}",
- .{e},
- ),
+ error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
+ else => |e| return e,
};
break :task;
}
@@ -5903,11 +5976,8 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) !bool {
);
defer sub_prog_node.end();
elf.flushLazy(pt, lmr) catch |err| switch (err) {
- error.OutOfMemory => |e| return e,
- else => |e| return comp.link_diags.fail(
- "linker failed to lower lazy {s}: {t}",
- .{ kind, e },
- ),
+ error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
+ else => |e| return e,
};
break :task;
};
@@ -5917,18 +5987,8 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) !bool {
const sub_prog_node = elf.idleProgNode(tid, elf.input_prog_node, elf.getNode(isi.node(elf)));
defer sub_prog_node.end();
elf.flushInputSection(isi) catch |err| switch (err) {
- else => |e| {
- const ii = isi.input(elf);
- return comp.link_diags.fail(
- "linker failed to read input section '{s}' from \"{f}{f}\": {t}",
- .{
- elf.getNode(isi.node(elf).parent(&elf.mf)).section.name(elf).slice(elf),
- ii.path(elf).fmtEscapeString(),
- fmtMemberString(ii.member(elf)),
- e,
- },
- );
- },
+ error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
+ else => |e| return e,
};
break :task;
}
@@ -6005,10 +6065,9 @@ fn flushUav(
elf: *Elf,
pt: Zcu.PerThread,
umi: Node.UavMapIndex,
-) !void {
+) Error!void {
const comp = elf.base.comp;
const gpa = comp.gpa;
- const zcu = pt.zcu;
const uav_val = umi.uavValue(elf);
const ni = umi.symbol(elf).index().ptr(elf).node;
@@ -6017,23 +6076,14 @@ fn flushUav(
var nw: MappedFile.Node.Writer = undefined;
ni.writer(&elf.mf, gpa, &nw);
defer nw.deinit();
- // TODO: UAV lowering should never require source locations.
- const dummy_src_loc: Zcu.LazySrcLoc = .{
- .base_node_inst = try zcu.intern_pool.trackZir(gpa, comp.io, pt.tid, .{
- .file = zcu.module_roots.get(zcu.std_mod).?.unwrap().?,
- .inst = .main_struct_inst,
- }),
- .offset = .{ .byte_abs = 0 },
- };
codegen.generateSymbol(
&elf.base,
pt,
- dummy_src_loc,
.fromInterned(uav_val),
&nw.interface,
.{ .atom_index = Node.toAtom(ni) },
) catch |err| switch (err) {
- error.WriteFailed => return error.OutOfMemory,
+ error.WriteFailed => return nw.err.?,
else => |e| return e,
};
switch (elf.symPtr(umi.symbol(elf).index())) {
@@ -6044,7 +6094,7 @@ fn flushUav(
assert(ni.hasMoved(&elf.mf));
}
-fn flushLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {
+fn flushLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) Error!void {
const zcu = pt.zcu;
const gpa = zcu.gpa;
@@ -6060,44 +6110,70 @@ fn flushLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {
var nw: MappedFile.Node.Writer = undefined;
ni.writer(&elf.mf, gpa, &nw);
defer nw.deinit();
- try codegen.generateLazySymbol(
+ codegen.generateLazySymbol(
&elf.base,
pt,
- Type.fromInterned(lazy.ty).srcLocOrNull(pt.zcu) orelse .unneeded,
lazy,
&required_alignment,
&nw.interface,
.none,
.{ .atom_index = Node.toAtom(ni) },
- );
+ ) catch |err| switch (err) {
+ error.WriteFailed => return nw.err.?,
+ else => |e| return e,
+ };
switch (elf.symPtr(lmr.symbol(elf).index())) {
inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)),
}
}
-fn flushInputSection(elf: *Elf, isi: InputSection.Index) !void {
+fn flushInputSection(elf: *Elf, isi: InputSection.Index) Error!void {
const file_loc = isi.fileLocation(elf);
if (file_loc.size == 0) return;
const comp = elf.base.comp;
const io = comp.io;
const gpa = comp.gpa;
+ const diags = &comp.link_diags;
const ii = isi.input(elf);
const path = ii.path(elf);
- const file = try path.root_dir.handle.openFile(io, path.sub_path, .{});
+ const file = path.root_dir.handle.openFile(io, path.sub_path, .{}) catch |err| switch (err) {
+ error.Canceled => |e| return e,
+ else => |e| return diags.fail("failed to open input file \"{f}\": {t}", .{ path.fmtEscapeString(), e }),
+ };
defer file.close(io);
var fr = file.reader(io, &.{});
- try fr.seekTo(file_loc.offset);
+ fr.seekTo(file_loc.offset) catch |err| switch (err) {
+ error.Canceled => |e| return e,
+ else => |e| return diags.fail("failed to read input section '{s}' from \"{f}{f}\": {t}", .{
+ elf.getNode(isi.node(elf).parent(&elf.mf)).section.name(elf).slice(elf),
+ path.fmtEscapeString(),
+ fmtMemberString(ii.member(elf)),
+ e,
+ }),
+ };
var nw: MappedFile.Node.Writer = undefined;
isi.node(elf).writer(&elf.mf, gpa, &nw);
defer nw.deinit();
- if (try nw.interface.sendFileAll(&fr, .limited(@intCast(file_loc.size))) != file_loc.size)
- return error.EndOfStream;
+ const n_bytes = nw.interface.sendFileAll(&fr, .limited(@intCast(file_loc.size))) catch |err| switch (err) {
+ error.ReadFailed => return diags.fail("failed to read input section '{s}' from \"{f}{f}\": {t}", .{
+ elf.getNode(isi.node(elf).parent(&elf.mf)).section.name(elf).slice(elf),
+ path.fmtEscapeString(),
+ fmtMemberString(ii.member(elf)),
+ fr.err orelse (fr.seek_err orelse fr.size_err.?),
+ }),
+ error.WriteFailed => return nw.err.?,
+ };
+ if (n_bytes != file_loc.size) return diags.fail("failed to read input section '{s}' from \"{f}{f}\": unexpected eof", .{
+ elf.getNode(isi.node(elf).parent(&elf.mf)).section.name(elf).slice(elf),
+ path.fmtEscapeString(),
+ fmtMemberString(ii.member(elf)),
+ });
// The input section should already be considered to have moved, because it is created as moved
// and pending calls to `flushInputSection` always happen before pending calls to `flushMoved`.
assert(isi.node(elf).hasMoved(&elf.mf));
}
-fn flushFileOffset(elf: *Elf, ni: MappedFile.Node.Index) !void {
+fn flushFileOffset(elf: *Elf, ni: MappedFile.Node.Index) void {
switch (elf.getNode(ni)) {
else => unreachable,
.ehdr => assert(ni.fileLocation(&elf.mf, false).offset == 0),
@@ -6118,7 +6194,7 @@ fn flushFileOffset(elf: *Elf, ni: MappedFile.Node.Index) !void {
},
}
var child_it = ni.children(&elf.mf);
- while (child_it.next()) |child_ni| try elf.flushFileOffset(child_ni);
+ while (child_it.next()) |child_ni| elf.flushFileOffset(child_ni);
},
.section => |shndx| switch (elf.shdrPtr(shndx)) {
inline else => |shdr| elf.targetStore(&shdr.offset, @intCast(
@@ -6128,14 +6204,14 @@ fn flushFileOffset(elf: *Elf, ni: MappedFile.Node.Index) !void {
}
}
-fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void {
+fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void {
const trace = tracy.trace(@src());
defer trace.end();
switch (elf.getNode(ni)) {
.file => unreachable,
- .ehdr, .shdr => try elf.flushFileOffset(ni),
+ .ehdr, .shdr => elf.flushFileOffset(ni),
.segment => |phndx| {
- try elf.flushFileOffset(ni);
+ elf.flushFileOffset(ni);
switch (elf.phdrSlice()) {
inline else => |phdr| {
const ph = &phdr[phndx];
@@ -6156,7 +6232,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void {
}
},
.section => |shndx| {
- try elf.flushFileOffset(ni);
+ elf.flushFileOffset(ni);
const addr = elf.computeNodeVAddr(ni);
const old_addr: u64, const flags: std.elf.SHF = switch (elf.shdrPtr(shndx)) {
inline else => |shdr| .{
@@ -6293,7 +6369,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void {
try ni.childrenMoved(elf.base.comp.gpa, &elf.mf);
}
-fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) !void {
+fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void {
const trace = tracy.trace(@src());
defer trace.end();
_, const size = ni.location(&elf.mf).resolve(&elf.mf);
@@ -6486,16 +6562,11 @@ pub fn updateExports(
pt: Zcu.PerThread,
exported: Zcu.Exported,
export_indices: []const Zcu.Export.Index,
-) !void {
+) link.Error!void {
+ const diags = &elf.base.comp.link_diags;
return elf.updateExportsInner(pt, exported, export_indices) catch |err| switch (err) {
- error.OutOfMemory => error.OutOfMemory,
- error.LinkFailure => error.AnalysisFail,
- else => |e| switch (elf.base.comp.link_diags.fail(
- "linker failed to update exports: {t}",
- .{e},
- )) {
- error.LinkFailure => return error.AnalysisFail,
- },
+ else => |e| return e,
+ error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
};
}
fn updateExportsInner(
@@ -6503,7 +6574,7 @@ fn updateExportsInner(
pt: Zcu.PerThread,
exported: Zcu.Exported,
export_indices: []const Zcu.Export.Index,
-) !void {
+) Error!void {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
@@ -6543,7 +6614,7 @@ fn updateExportsInner(
.internal => @panic("TODO internal linkage"),
.strong => .strong,
.weak => .weak,
- .link_once => return error.LinkOnceUnsupported,
+ .link_once => return elf.base.comp.link_diags.fail("TODO(Elf2): link_once is not supported", .{}),
},
.visibility = switch (@"export".opts.visibility) {
.default => .DEFAULT,
@@ -6591,10 +6662,10 @@ pub fn dump(elf: *Elf, tid: Zcu.PerThread.Id) Io.Cancelable!void {
pub fn printNode(
elf: *Elf,
tid: Zcu.PerThread.Id,
- w: *std.Io.Writer,
+ w: *Io.Writer,
ni: MappedFile.Node.Index,
indent: usize,
-) !void {
+) Io.Writer.Error!void {
const node = elf.getNode(ni);
try w.splatByteAll(' ', indent);
try w.writeAll(@tagName(node));
@@ -6698,3 +6769,15 @@ pub fn printNode(
try w.writeByte('\n');
}
}
+
+fn ensureNodeSize(
+ elf: *Elf,
+ node: MappedFile.Node.Index,
+ need_size: u64,
+) Error!void {
+ _, const node_size = node.location(&elf.mf).resolve(&elf.mf);
+ if (need_size <= node_size) return;
+ const gpa = elf.base.comp.gpa;
+ const new_size = need_size + need_size / MappedFile.growth_factor;
+ try node.resize(&elf.mf, gpa, new_size);
+}
diff --git a/src/link/LdScript.zig b/src/link/LdScript.zig
@@ -13,7 +13,7 @@ pub fn deinit(ls: *LdScript, gpa: Allocator) void {
}
pub const Error = error{
- LinkFailure,
+ AlreadyReported,
UnknownCpuArch,
OutOfMemory,
};
diff --git a/src/link/Lld.zig b/src/link/Lld.zig
@@ -255,7 +255,7 @@ pub fn flush(
arena: Allocator,
tid: Zcu.PerThread.Id,
prog_node: std.Progress.Node,
-) link.File.FlushError!void {
+) link.Error!void {
dev.check(.lld_linker);
_ = tid;
@@ -277,7 +277,7 @@ pub fn flush(
.wasm => wasmLink(lld, arena),
};
result catch |err| switch (err) {
- error.OutOfMemory, error.LinkFailure => |e| return e,
+ error.OutOfMemory, error.AlreadyReported => |e| return e,
else => |e| return lld.base.comp.link_diags.fail("failed to link with LLD: {t}", .{e}),
};
}
@@ -1620,7 +1620,7 @@ fn spawnLld(comp: *Compilation, arena: Allocator, argv: []const []const u8) !voi
const exit_code = try lldMain(arena, argv, false);
if (exit_code == 0) return;
if (comp.clang_passthrough_mode) std.process.exit(exit_code);
- return error.LinkFailure;
+ return error.AlreadyReported;
}
var stderr: []u8 = &.{};
@@ -1720,7 +1720,7 @@ fn spawnLld(comp: *Compilation, arena: Allocator, argv: []const []const u8) !voi
.exited => |code| if (code != 0) {
if (comp.clang_passthrough_mode) std.process.exit(code);
diags.lockAndParseLldStderr(argv[1], stderr);
- return error.LinkFailure;
+ return error.AlreadyReported;
},
.signal => |sig| {
if (comp.clang_passthrough_mode) std.process.abort();
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
@@ -341,7 +341,7 @@ pub fn flush(
arena: Allocator,
tid: Zcu.PerThread.Id,
prog_node: std.Progress.Node,
-) link.File.FlushError!void {
+) link.Error!void {
const tracy = trace(@src());
defer tracy.end();
@@ -490,7 +490,7 @@ pub fn flush(
}
};
- if (diags.hasErrors()) return error.LinkFailure;
+ if (diags.hasErrors()) return error.AlreadyReported;
{
const index = @as(File.Index, @intCast(try self.files.addOne(gpa)));
@@ -504,7 +504,7 @@ pub fn flush(
try self.resolveSymbols();
try self.convertTentativeDefsAndResolveSpecialSymbols();
self.dedupLiterals() catch |err| switch (err) {
- error.LinkFailure => |e| return e,
+ error.AlreadyReported => |e| return e,
else => |e| return diags.fail("failed to deduplicate literals: {s}", .{@errorName(e)}),
};
@@ -513,7 +513,7 @@ pub fn flush(
}
self.checkDuplicates() catch |err| switch (err) {
- error.HasDuplicates => return error.LinkFailure,
+ error.HasDuplicates => return error.AlreadyReported,
else => |e| return diags.fail("failed to check for duplicate symbol definitions: {s}", .{@errorName(e)}),
};
@@ -528,7 +528,7 @@ pub fn flush(
self.claimUnresolved();
self.scanRelocs() catch |err| switch (err) {
- error.HasUndefinedSymbols => return error.LinkFailure,
+ error.HasUndefinedSymbols => return error.AlreadyReported,
else => |e| return diags.fail("failed to scan relocations: {s}", .{@errorName(e)}),
};
@@ -542,7 +542,7 @@ pub fn flush(
try self.initSegments();
self.allocateSections() catch |err| switch (err) {
- error.LinkFailure => |e| return e,
+ error.AlreadyReported => |e| return e,
else => |e| return diags.fail("failed to allocate sections: {s}", .{@errorName(e)}),
};
self.allocateSegments();
@@ -558,7 +558,7 @@ pub fn flush(
if (self.getZigObject()) |zo| {
zo.resolveRelocs(self) catch |err| switch (err) {
- error.ResolveFailed => return error.LinkFailure,
+ error.ResolveFailed => return error.AlreadyReported,
else => |e| return e,
};
}
@@ -567,7 +567,7 @@ pub fn flush(
try self.writeSectionsToFile();
try self.allocateLinkeditSegment();
self.writeLinkeditSectionsToFile() catch |err| switch (err) {
- error.OutOfMemory, error.LinkFailure => |e| return e,
+ error.OutOfMemory, error.AlreadyReported => |e| return e,
else => |e| return diags.fail("failed to write linkedit sections to file: {t}", .{e}),
};
@@ -594,11 +594,11 @@ pub fn flush(
const ncmds, const sizeofcmds, const uuid_cmd_offset = self.writeLoadCommands() catch |err| switch (err) {
error.WriteFailed => unreachable,
- error.OutOfMemory, error.LinkFailure => |e| return e,
+ error.OutOfMemory, error.AlreadyReported => |e| return e,
};
try self.writeHeader(ncmds, sizeofcmds);
self.writeUuid(uuid_cmd_offset, self.requiresCodeSig()) catch |err| switch (err) {
- error.OutOfMemory, error.LinkFailure => |e| return e,
+ error.OutOfMemory, error.AlreadyReported => |e| return e,
else => |e| return diags.fail("failed to calculate and write uuid: {s}", .{@errorName(e)}),
};
if (self.getDebugSymbols()) |dsym| dsym.flush(self) catch |err| switch (err) {
@@ -609,7 +609,7 @@ pub fn flush(
// Code signing always comes last.
if (codesig) |*csig| {
self.writeCodeSignature(csig) catch |err| switch (err) {
- error.OutOfMemory, error.LinkFailure => |e| return e,
+ error.OutOfMemory, error.AlreadyReported => |e| return e,
else => |e| return diags.fail("failed to write code signature: {s}", .{@errorName(e)}),
};
const emit = self.base.emit;
@@ -968,7 +968,7 @@ pub fn parseInputFiles(self: *MachO) !void {
}
}
- if (diags.hasErrors()) return error.LinkFailure;
+ if (diags.hasErrors()) return error.AlreadyReported;
}
fn parseInputFileWorker(self: *MachO, file: File) void {
@@ -1365,7 +1365,7 @@ fn convertTentativeDefsAndResolveSpecialSymbols(self: *MachO) !void {
resolveSpecialSymbolsWorker(self, obj);
}
}
- if (diags.hasErrors()) return error.LinkFailure;
+ if (diags.hasErrors()) return error.AlreadyReported;
}
fn convertTentativeDefinitionsWorker(self: *MachO, object: *Object) void {
@@ -1450,7 +1450,7 @@ fn checkDuplicates(self: *MachO) !void {
}
}
- if (diags.hasErrors()) return error.LinkFailure;
+ if (diags.hasErrors()) return error.AlreadyReported;
try self.reportDuplicates();
}
@@ -1517,7 +1517,7 @@ fn scanRelocs(self: *MachO) !void {
}
}
- if (diags.hasErrors()) return error.LinkFailure;
+ if (diags.hasErrors()) return error.AlreadyReported;
if (self.getInternalObject()) |obj| {
try obj.checkUndefs(self);
@@ -1990,7 +1990,7 @@ fn calcSectionSizes(self: *MachO) !void {
}
}
- if (diags.hasErrors()) return error.LinkFailure;
+ if (diags.hasErrors()) return error.AlreadyReported;
try self.calcSymtabSize();
@@ -2527,7 +2527,7 @@ fn writeSectionsAndUpdateLinkeditSizes(self: *MachO) !void {
};
}
- if (diags.hasErrors()) return error.LinkFailure;
+ if (diags.hasErrors()) return error.AlreadyReported;
}
fn writeAtomsWorker(self: *MachO, file: File) void {
@@ -3074,15 +3074,15 @@ pub fn updateFunc(
pt: Zcu.PerThread,
func_index: InternPool.Index,
mir: *const codegen.AnyMir,
-) link.File.UpdateNavError!void {
+) link.Error!void {
return self.getZigObject().?.updateFunc(self, pt, func_index, mir);
}
-pub fn updateNav(self: *MachO, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.File.UpdateNavError!void {
+pub fn updateNav(self: *MachO, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.Error!void {
return self.getZigObject().?.updateNav(self, pt, nav);
}
-pub fn updateLineNumber(self: *MachO, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {
+pub fn updateLineNumber(self: *MachO, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) link.Error!void {
return self.getZigObject().?.updateLineNumber(pt, ti_id);
}
@@ -3091,7 +3091,7 @@ pub fn updateExports(
pt: Zcu.PerThread,
exported: Zcu.Exported,
export_indices: []const Zcu.Export.Index,
-) link.File.UpdateExportsError!void {
+) link.Error!void {
return self.getZigObject().?.updateExports(self, pt, exported, export_indices);
}
@@ -3116,9 +3116,8 @@ pub fn lowerUav(
pt: Zcu.PerThread,
uav: InternPool.Index,
explicit_alignment: InternPool.Alignment,
- src_loc: Zcu.LazySrcLoc,
-) !codegen.SymbolResult {
- return self.getZigObject().?.lowerUav(self, pt, uav, explicit_alignment, src_loc);
+) !link.File.SymbolId {
+ return self.getZigObject().?.lowerUav(self, pt, uav, explicit_alignment);
}
pub 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
file_writer.pos = new_offset;
const size_u = math.cast(usize, size) orelse return error.Overflow;
const n = file_writer.interface.sendFileAll(&file_reader, .limited(size_u)) catch |err| switch (err) {
- error.ReadFailed => return file_reader.err.?,
+ error.ReadFailed => switch (file_reader.err.?) {
+ error.ConnectionResetByPeer => return error.Unexpected, // not a socket
+ error.SocketUnconnected => return error.Unexpected, // not a socket
+ else => |e| return e,
+ },
error.WriteFailed => return file_writer.err.?,
};
assert(n == size_u);
@@ -5373,7 +5376,7 @@ fn isReachable(atom: *const Atom, rel: Relocation, macho_file: *MachO) bool {
return true;
}
-pub fn pwriteAll(macho_file: *MachO, bytes: []const u8, offset: u64) error{LinkFailure}!void {
+pub fn pwriteAll(macho_file: *MachO, bytes: []const u8, offset: u64) error{AlreadyReported}!void {
const comp = macho_file.base.comp;
const io = comp.io;
const diags = &comp.link_diags;
@@ -5381,7 +5384,7 @@ pub fn pwriteAll(macho_file: *MachO, bytes: []const u8, offset: u64) error{LinkF
return diags.fail("failed to write: {t}", .{err});
}
-pub fn setLength(macho_file: *MachO, length: u64) error{LinkFailure}!void {
+pub fn setLength(macho_file: *MachO, length: u64) error{AlreadyReported}!void {
const comp = macho_file.base.comp;
const io = comp.io;
const diags = &comp.link_diags;
@@ -5389,7 +5392,7 @@ pub fn setLength(macho_file: *MachO, length: u64) error{LinkFailure}!void {
return diags.fail("failed to set file end pos: {t}", .{err});
}
-pub fn cast(macho_file: *MachO, comptime T: type, x: anytype) error{LinkFailure}!T {
+pub fn cast(macho_file: *MachO, comptime T: type, x: anytype) error{AlreadyReported}!T {
return std.math.cast(T, x) orelse {
const comp = macho_file.base.comp;
const diags = &comp.link_diags;
@@ -5397,7 +5400,7 @@ pub fn cast(macho_file: *MachO, comptime T: type, x: anytype) error{LinkFailure}
};
}
-pub fn alignPow(macho_file: *MachO, x: u32) error{LinkFailure}!u32 {
+pub fn alignPow(macho_file: *MachO, x: u32) error{AlreadyReported}!u32 {
const result, const ov = @shlWithOverflow(@as(u32, 1), try cast(macho_file, u5, x));
if (ov != 0) {
const comp = macho_file.base.comp;
diff --git a/src/link/MachO/Atom.zig b/src/link/MachO/Atom.zig
@@ -930,7 +930,7 @@ pub fn calcNumRelocs(self: Atom, macho_file: *MachO) u32 {
}
}
-pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.relocation_info) error{ LinkFailure, OutOfMemory }!void {
+pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.relocation_info) error{ AlreadyReported, OutOfMemory }!void {
const tracy = trace(@src());
defer tracy.end();
diff --git a/src/link/MachO/InternalObject.zig b/src/link/MachO/InternalObject.zig
@@ -648,7 +648,7 @@ fn addSection(self: *InternalObject, allocator: Allocator, segname: []const u8,
return n_sect;
}
-fn getSectionData(self: *const InternalObject, index: u32, macho_file: *MachO) error{LinkFailure}![]const u8 {
+fn getSectionData(self: *const InternalObject, index: u32, macho_file: *MachO) error{AlreadyReported}![]const u8 {
const slice = self.sections.slice();
assert(index < slice.items(.header).len);
const sect = slice.items(.header)[index];
diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig
@@ -427,7 +427,7 @@ pub fn calcNumRelocs(self: *ZigObject, macho_file: *MachO) void {
}
}
-pub fn writeRelocs(self: *ZigObject, macho_file: *MachO) error{ LinkFailure, OutOfMemory }!void {
+pub fn writeRelocs(self: *ZigObject, macho_file: *MachO) error{ AlreadyReported, OutOfMemory }!void {
const gpa = macho_file.base.comp.gpa;
const diags = &macho_file.base.comp.link_diags;
@@ -555,7 +555,7 @@ pub fn getInputSection(self: ZigObject, atom: Atom, macho_file: *MachO) macho.se
return sect;
}
-pub fn flush(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.File.FlushError!void {
+pub fn flush(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.Error!void {
const diags = &macho_file.base.comp.link_diags;
// 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
.{ .kind = .code, .ty = .anyerror_type },
metadata.text_symbol_index,
) catch |err| switch (err) {
- error.OutOfMemory, error.LinkFailure => |e| return e,
+ error.OutOfMemory, error.AlreadyReported => |e| return e,
else => |e| return diags.fail("failed to update lazy symbol: {s}", .{@errorName(e)}),
};
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
.{ .kind = .const_data, .ty = .anyerror_type },
metadata.const_symbol_index,
) catch |err| switch (err) {
- error.OutOfMemory, error.LinkFailure => |e| return e,
+ error.OutOfMemory, error.AlreadyReported => |e| return e,
else => |e| return diags.fail("failed to update lazy symbol: {s}", .{@errorName(e)}),
};
}
@@ -704,8 +704,7 @@ pub fn lowerUav(
pt: Zcu.PerThread,
uav: InternPool.Index,
explicit_alignment: Atom.Alignment,
- src_loc: Zcu.LazySrcLoc,
-) !codegen.SymbolResult {
+) !link.File.SymbolId {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const val = Value.fromInterned(uav);
@@ -717,35 +716,29 @@ pub fn lowerUav(
const sym = self.symbols.items[metadata.symbol_index];
const existing_alignment = sym.getAtom(macho_file).?.alignment;
if (uav_alignment.order(existing_alignment).compare(.lte))
- return .{ .sym_index = @enumFromInt(metadata.symbol_index) };
+ return @enumFromInt(metadata.symbol_index);
}
var name_buf: [32]u8 = undefined;
const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{
@intFromEnum(uav),
}) catch unreachable;
- const res = self.lowerConst(
+ const sym_index = self.lowerConst(
macho_file,
pt,
name,
val,
uav_alignment,
macho_file.zig_const_sect_index.?,
- src_loc,
) catch |err| switch (err) {
error.OutOfMemory => |e| return e,
- else => |e| return .{ .fail = try Zcu.ErrorMsg.create(
- gpa,
- src_loc,
- "unable to lower constant value: {s}",
- .{@errorName(e)},
- ) },
+ else => |e| return macho_file.base.comp.link_diags.fail(
+ "failed to lower constant value: {t}",
+ .{e},
+ ),
};
- switch (res) {
- .sym_index => |sym_index| try self.uavs.put(gpa, uav, .{ .symbol_index = @intFromEnum(sym_index) }),
- .fail => {},
- }
- return res;
+ try self.uavs.put(gpa, uav, .{ .symbol_index = @intFromEnum(sym_index) });
+ return sym_index;
}
fn freeNavMetadata(self: *ZigObject, macho_file: *MachO, sym_index: Symbol.Index) void {
@@ -776,7 +769,7 @@ pub fn updateFunc(
pt: Zcu.PerThread,
func_index: InternPool.Index,
mir: *const codegen.AnyMir,
-) link.File.UpdateNavError!void {
+) link.Error!void {
const tracy = trace(@src());
defer tracy.end();
@@ -796,7 +789,6 @@ pub fn updateFunc(
codegen.emitFunction(
&macho_file.base,
pt,
- zcu.navSrcLoc(func.owner_nav),
func_index,
@enumFromInt(sym_index),
mir,
@@ -867,7 +859,7 @@ pub fn updateNav(
macho_file: *MachO,
pt: Zcu.PerThread,
nav_index: InternPool.Nav.Index,
-) link.File.UpdateNavError!void {
+) link.Error!void {
const tracy = trace(@src());
defer tracy.end();
@@ -887,7 +879,7 @@ pub fn updateNav(
var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, @enumFromInt(sym_index));
defer debug_wip_nav.deinit();
dwarf.finishWipNav(pt, nav_index, &debug_wip_nav) catch |err| switch (err) {
- error.OutOfMemory, error.Overflow => |e| return e,
+ error.OutOfMemory, error.Canceled, error.AlreadyReported => |e| return e,
else => |e| return macho_file.base.cgFail(nav_index, "failed to finish dwarf nav: {s}", .{@errorName(e)}),
};
}
@@ -908,7 +900,6 @@ pub fn updateNav(
codegen.generateSymbol(
&macho_file.base,
pt,
- zcu.navSrcLoc(nav_index),
.fromInterned(nav.resolved.?.value),
&aw.writer,
.{ .atom_index = @enumFromInt(sym_index) },
@@ -925,7 +916,7 @@ pub fn updateNav(
try self.updateNavCode(macho_file, pt, nav_index, sym_index, sect_index, code);
if (debug_wip_nav) |*wip_nav| self.dwarf.?.finishWipNav(pt, nav_index, wip_nav) catch |err| switch (err) {
- error.OutOfMemory, error.Overflow => |e| return e,
+ error.OutOfMemory, error.Canceled, error.AlreadyReported => |e| return e,
else => |e| return macho_file.base.cgFail(nav_index, "failed to finish dwarf nav: {s}", .{@errorName(e)}),
};
} else if (self.dwarf) |*dwarf| try dwarf.updateComptimeNav(pt, nav_index);
@@ -941,7 +932,7 @@ fn updateNavCode(
sym_index: Symbol.Index,
sect_index: u8,
code: []const u8,
-) link.File.UpdateNavError!void {
+) link.Error!void {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const comp = zcu.comp;
@@ -1198,8 +1189,7 @@ fn lowerConst(
val: Value,
required_alignment: Atom.Alignment,
output_section_index: u8,
- src_loc: Zcu.LazySrcLoc,
-) !codegen.SymbolResult {
+) !link.File.SymbolId {
const gpa = macho_file.base.comp.gpa;
var aw: std.Io.Writer.Allocating = .init(gpa);
@@ -1211,7 +1201,6 @@ fn lowerConst(
codegen.generateSymbol(
&macho_file.base,
pt,
- src_loc,
val,
&aw.writer,
.{ .atom_index = @enumFromInt(sym_index) },
@@ -1242,7 +1231,7 @@ fn lowerConst(
const file_offset = sect.offset + atom.value;
try macho_file.pwriteAll(code, file_offset);
- return .{ .sym_index = @enumFromInt(sym_index) };
+ return @enumFromInt(sym_index);
}
pub fn updateExports(
@@ -1251,7 +1240,7 @@ pub fn updateExports(
pt: Zcu.PerThread,
exported: Zcu.Exported,
export_indices: []const Zcu.Export.Index,
-) link.File.UpdateExportsError!void {
+) link.Error!void {
const tracy = trace(@src());
defer tracy.end();
@@ -1263,18 +1252,7 @@ pub fn updateExports(
break :blk self.navs.getPtr(nav).?;
},
.uav => |uav| self.uavs.getPtr(uav) orelse blk: {
- const first_exp = export_indices[0].ptr(zcu);
- const res = try self.lowerUav(macho_file, pt, uav, .none, first_exp.src);
- switch (res) {
- .sym_index => {},
- .fail => |em| {
- // TODO maybe it's enough to return an error here and let Zcu.processExportsInner
- // handle the error?
- try zcu.failed_exports.ensureUnusedCapacity(zcu.gpa, 1);
- zcu.failed_exports.putAssumeCapacityNoClobber(export_indices[0], em);
- return;
- },
- }
+ _ = try self.lowerUav(macho_file, pt, uav, .none);
break :blk self.uavs.getPtr(uav).?;
},
};
@@ -1368,11 +1346,9 @@ fn updateLazySymbol(
break :blk try self.addString(gpa, name);
};
- const src = Type.fromInterned(lazy_sym.ty).srcLocOrNull(zcu) orelse Zcu.LazySrcLoc.unneeded;
try codegen.generateLazySymbol(
&macho_file.base,
pt,
- src,
lazy_sym,
&required_alignment,
&aw.writer,
@@ -1413,12 +1389,12 @@ fn updateLazySymbol(
try macho_file.pwriteAll(code, file_offset);
}
-pub fn updateLineNumber(self: *ZigObject, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {
+pub fn updateLineNumber(self: *ZigObject, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) link.Error!void {
if (self.dwarf) |*dwarf| {
const comp = dwarf.bin_file.comp;
const diags = &comp.link_diags;
dwarf.updateLineNumber(pt.zcu, ti_id) catch |err| switch (err) {
- error.Overflow, error.OutOfMemory => |e| return e,
+ error.OutOfMemory, error.Canceled, error.AlreadyReported => |e| return e,
else => |e| return diags.fail("failed to update dwarf line numbers: {s}", .{@errorName(e)}),
};
}
diff --git a/src/link/MachO/relocatable.zig b/src/link/MachO/relocatable.zig
@@ -1,4 +1,4 @@
-pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Path) link.File.FlushError!void {
+pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Path) link.Error!void {
const gpa = comp.gpa;
const io = comp.io;
const diags = &comp.link_diags;
@@ -34,15 +34,15 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat
diags.addParseError(link_input.path().?, "failed to read input file: {s}", .{@errorName(err)});
}
- if (diags.hasErrors()) return error.LinkFailure;
+ if (diags.hasErrors()) return error.AlreadyReported;
try macho_file.parseInputFiles();
- if (diags.hasErrors()) return error.LinkFailure;
+ if (diags.hasErrors()) return error.AlreadyReported;
try macho_file.resolveSymbols();
macho_file.dedupLiterals() catch |err| switch (err) {
- error.OutOfMemory, error.LinkFailure => |e| return e,
+ error.OutOfMemory, error.AlreadyReported => |e| return e,
else => |e| return diags.fail("failed to update ar size: {s}", .{@errorName(e)}),
};
markExports(macho_file);
@@ -54,7 +54,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat
try createSegment(macho_file);
allocateSections(macho_file) catch |err| switch (err) {
- error.LinkFailure => |e| return e,
+ error.AlreadyReported => |e| return e,
else => |e| return diags.fail("failed to allocate sections: {s}", .{@errorName(e)}),
};
allocateSegment(macho_file);
@@ -75,7 +75,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat
try writeHeader(macho_file, ncmds, sizeofcmds);
}
-pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Path) link.File.FlushError!void {
+pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Path) link.Error!void {
const gpa = comp.gpa;
const io = comp.io;
const diags = &macho_file.base.comp.link_diags;
@@ -105,11 +105,11 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?
diags.addParseError(link_input.path().?, "failed to read input file: {s}", .{@errorName(err)});
}
- if (diags.hasErrors()) return error.LinkFailure;
+ if (diags.hasErrors()) return error.AlreadyReported;
try parseInputFilesAr(macho_file);
- if (diags.hasErrors()) return error.LinkFailure;
+ if (diags.hasErrors()) return error.AlreadyReported;
// First, we flush relocatable object file generated with our backends.
if (macho_file.getZigObject()) |zo| {
@@ -231,7 +231,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?
try macho_file.setLength(total_size);
try macho_file.pwriteAll(writer.buffered(), 0);
- if (diags.hasErrors()) return error.LinkFailure;
+ if (diags.hasErrors()) return error.AlreadyReported;
}
fn parseInputFilesAr(macho_file: *MachO) !void {
@@ -339,7 +339,7 @@ fn calcSectionSizes(macho_file: *MachO) !void {
}
try calcSymtabSize(macho_file);
- if (diags.hasErrors()) return error.LinkFailure;
+ if (diags.hasErrors()) return error.AlreadyReported;
}
fn calcSectionSizeWorker(macho_file: *MachO, sect_id: u8) void {
@@ -586,7 +586,7 @@ fn sortRelocs(macho_file: *MachO) void {
}
}
-fn writeSections(macho_file: *MachO) link.File.FlushError!void {
+fn writeSections(macho_file: *MachO) link.Error!void {
const tracy = trace(@src());
defer tracy.end();
@@ -632,7 +632,7 @@ fn writeSections(macho_file: *MachO) link.File.FlushError!void {
}
}
- if (diags.hasErrors()) return error.LinkFailure;
+ if (diags.hasErrors()) return error.AlreadyReported;
if (macho_file.getZigObject()) |zo| {
try zo.writeRelocs(macho_file);
@@ -685,7 +685,7 @@ fn writeSectionsToFile(macho_file: *MachO) !void {
try macho_file.pwriteAll(macho_file.strtab.items, macho_file.symtab_cmd.stroff);
}
-fn writeLoadCommands(macho_file: *MachO) error{ LinkFailure, OutOfMemory }!struct { usize, usize } {
+fn writeLoadCommands(macho_file: *MachO) error{ AlreadyReported, OutOfMemory }!struct { usize, usize } {
const gpa = macho_file.base.comp.gpa;
const needed_size = load_commands.calcLoadCommandsSizeObject(macho_file);
const buffer = try gpa.alloc(u8, needed_size);
diff --git a/src/link/MappedFile.zig b/src/link/MappedFile.zig
@@ -5,6 +5,7 @@ const is_linux = builtin.os.tag == .linux;
const is_windows = builtin.os.tag == .windows;
const std = @import("std");
+const Allocator = std.mem.Allocator;
const Io = std.Io;
const assert = std.debug.assert;
const linux = std.os.linux;
@@ -24,14 +25,40 @@ large: std.ArrayList(u64),
updates: std.ArrayList(Node.Index),
update_prog_node: std.Progress.Node,
writers: std.SinglyLinkedList,
+io_err: ?IoError,
pub const growth_factor = 4;
-pub const Error = error{
+pub const IoError = Io.UnexpectedError || error{
+ DiskQuota,
+ FileTooBig,
+ InputOutput,
+ NoSpaceLeft,
+ AccessDenied,
+ PermissionDenied,
+ SystemResources,
+ LockViolation,
+ LockedMemoryLimitExceeded,
+ ProcessFdQuotaExceeded,
+ SystemFdQuotaExceeded,
+ FileBusy,
+ DeviceBusy,
+ NoDevice,
+ PathAlreadyExists,
+ IsDir,
NotFile,
-} || Io.File.MemoryMap.CreateError || Io.File.MemoryMap.SetLengthError || Io.File.WritePositionalError;
+ BrokenPipe,
+ NonResizable,
+ Unseekable,
+};
+
+pub const Error = Allocator.Error || Io.Cancelable || error{
+ /// Some I/O operation on the memory-mapped file failed. The underlying error is available in
+ /// the `MappedFile.io_err` field.
+ MappedFileIo,
+};
-pub fn init(file: Io.File, gpa: std.mem.Allocator, io: Io) !MappedFile {
+pub fn init(file: Io.File, gpa: std.mem.Allocator, io: Io) (Allocator.Error || Io.Cancelable || IoError)!MappedFile {
var mf: MappedFile = .{
.io = io,
.flags = undefined,
@@ -47,10 +74,14 @@ pub fn init(file: Io.File, gpa: std.mem.Allocator, io: Io) !MappedFile {
.updates = .empty,
.update_prog_node = .none,
.writers = .{},
+ .io_err = null,
};
errdefer mf.deinit(gpa);
const size: u64, const block_size = stat: {
- const stat = try file.stat(io);
+ const stat = file.stat(io) catch |err| switch (err) {
+ error.Streaming => return error.PathAlreadyExists,
+ else => |e| return e,
+ };
if (stat.kind != .file) return error.PathAlreadyExists;
break :stat .{ stat.size, @max(std.heap.pageSize(), stat.block_size) };
};
@@ -61,14 +92,16 @@ pub fn init(file: Io.File, gpa: std.mem.Allocator, io: Io) !MappedFile {
.fallocate_punch_hole_unsupported = false,
};
try mf.nodes.ensureUnusedCapacity(gpa, 1);
- assert(try mf.addNode(gpa, .{
- .add_node = .{
- .size = size,
- .alignment = mf.flags.block_size,
- .fixed = true,
- },
- }) == Node.Index.root);
- try mf.ensureTotalCapacity(@intCast(size));
+ const root_ni = mf.addNode(gpa, .{ .add_node = .{
+ .size = size,
+ .alignment = mf.flags.block_size,
+ .fixed = true,
+ } }) catch |err| switch (err) {
+ error.MappedFileIo => return mf.io_err.?,
+ else => |e| return e,
+ };
+ assert(root_ni == Node.Index.root);
+ try mf.ensureTotalCapacityInner(@intCast(size));
return mf;
}
@@ -174,7 +207,7 @@ pub const Node = extern struct {
return .{ .mf = mf, .ni = ni.get(mf).last };
}
- pub fn childrenMoved(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) !void {
+ pub fn childrenMoved(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) Allocator.Error!void {
var child_ni = ni.get(mf).last;
while (child_ni != .none) {
try child_ni.moved(gpa, mf);
@@ -192,7 +225,7 @@ pub const Node = extern struct {
}
return false;
}
- pub fn moved(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) !void {
+ pub fn moved(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) Allocator.Error!void {
try mf.updates.ensureUnusedCapacity(gpa, 1);
ni.movedAssumeCapacity(mf);
}
@@ -213,7 +246,7 @@ pub const Node = extern struct {
pub fn hasResized(ni: Node.Index, mf: *const MappedFile) bool {
return ni.get(mf).flags.resized;
}
- pub fn resized(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) !void {
+ pub fn resized(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) Allocator.Error!void {
try mf.updates.ensureUnusedCapacity(gpa, 1);
ni.resizedAssumeCapacity(mf);
}
@@ -296,8 +329,16 @@ pub const Node = extern struct {
return mf.memory_map.memory[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)];
}
- pub fn resize(ni: Node.Index, mf: *MappedFile, gpa: std.mem.Allocator, size: u64) !void {
- try mf.resizeNode(gpa, ni, size);
+ pub fn resize(ni: Node.Index, mf: *MappedFile, gpa: std.mem.Allocator, size: u64) Error!void {
+ mf.resizeNode(gpa, ni, size) catch |err| switch (err) {
+ error.OutOfMemory,
+ error.Canceled,
+ => |e| return e,
+ else => |e| {
+ mf.io_err = e;
+ return error.MappedFileIo;
+ },
+ };
var writers_it = mf.writers.first;
while (writers_it) |writer_node| : (writers_it = writer_node.next) {
const w: *Node.Writer = @fieldParentPtr("writer_node", writer_node);
@@ -313,8 +354,16 @@ pub const Node = extern struct {
mf: *MappedFile,
gpa: std.mem.Allocator,
new_alignment: std.mem.Alignment,
- ) !void {
- try mf.realignNode(gpa, ni, new_alignment);
+ ) Error!void {
+ mf.realignNode(gpa, ni, new_alignment) catch |err| switch (err) {
+ error.OutOfMemory,
+ error.Canceled,
+ => |e| return e,
+ else => |e| {
+ mf.io_err = e;
+ return error.MappedFileIo;
+ },
+ };
var writers_it = mf.writers.first;
while (writers_it) |writer_node| : (writers_it = writer_node.next) {
const w: *Node.Writer = @fieldParentPtr("writer_node", writer_node);
@@ -422,9 +471,16 @@ pub const Node = extern struct {
file_reader.pos,
w.ni.fileLocation(w.mf, true).offset + interface.end,
limit.minInt(interface.unusedCapacityLen()),
- ) catch |err| {
- w.err = err;
- return error.WriteFailed;
+ ) catch |err| switch (err) {
+ error.Canceled => |e| {
+ w.err = e;
+ return error.WriteFailed;
+ },
+ else => |e| {
+ w.mf.io_err = e;
+ w.err = error.MappedFileIo;
+ return error.WriteFailed;
+ },
});
if (n == 0) return error.Unimplemented;
file_reader.pos += n;
@@ -472,7 +528,7 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {
next: Node.Index = .none,
offset: u64 = 0,
add_node: AddNodeOptions,
-}) !Node.Index {
+}) Error!Node.Index {
if (opts.add_node.moved or opts.add_node.resized) try mf.updates.ensureUnusedCapacity(gpa, 1);
const offset = opts.add_node.alignment.forward(@intCast(opts.offset));
const location_tag: Node.Location.Tag, const location_payload: Node.Location.Payload = location: {
@@ -544,7 +600,7 @@ pub fn addOnlyChildNode(
gpa: std.mem.Allocator,
parent_ni: Node.Index,
opts: AddNodeOptions,
-) !Node.Index {
+) Error!Node.Index {
try mf.nodes.ensureUnusedCapacity(gpa, 1);
const parent = parent_ni.get(mf);
assert(parent.first == .none and parent.last == .none);
@@ -559,7 +615,7 @@ pub fn addFirstChildNode(
gpa: std.mem.Allocator,
parent_ni: Node.Index,
opts: AddNodeOptions,
-) !Node.Index {
+) Error!Node.Index {
try mf.nodes.ensureUnusedCapacity(gpa, 1);
const parent = parent_ni.get(mf);
return mf.addNode(gpa, .{
@@ -574,7 +630,7 @@ pub fn addLastChildNode(
gpa: std.mem.Allocator,
parent_ni: Node.Index,
opts: AddNodeOptions,
-) !Node.Index {
+) Error!Node.Index {
try mf.nodes.ensureUnusedCapacity(gpa, 1);
const parent = parent_ni.get(mf);
return mf.addNode(gpa, .{
@@ -596,7 +652,7 @@ pub fn addNodeAfter(
gpa: std.mem.Allocator,
prev_ni: Node.Index,
opts: AddNodeOptions,
-) !Node.Index {
+) Error!Node.Index {
assert(prev_ni != .none);
try mf.nodes.ensureUnusedCapacity(gpa, 1);
const prev = prev_ni.get(mf);
@@ -610,7 +666,7 @@ pub fn addNodeAfter(
});
}
-fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested_size: u64) !void {
+fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested_size: u64) (Allocator.Error || Io.Cancelable || IoError)!void {
const io = mf.io;
const node = ni.get(mf);
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
// Resize the entire file
if (ni == Node.Index.root) {
try mf.ensureCapacityForSetLocation(gpa);
- try mf.memory_map.write(io);
+ mf.memory_map.write(io) catch |err| switch (err) {
+ error.WouldBlock => return error.Unexpected, // file was not opened as non-blocking
+ error.NotOpenForWriting => return error.Unexpected, // we definitely opened the file for writing
+ else => |e| return e,
+ };
try mf.memory_map.file.setLength(io, new_size);
- try mf.ensureTotalCapacity(@intCast(new_size));
+ try mf.ensureTotalCapacityInner(@intCast(new_size));
ni.setLocationAssumeCapacity(mf, old_offset, new_size);
return;
}
@@ -643,7 +703,11 @@ fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested
if (is_linux and !mf.flags.fallocate_insert_range_unsupported and
node.flags.alignment.order(mf.flags.block_size).compare(.gte))
insert_range: {
- try mf.memory_map.write(io);
+ mf.memory_map.write(io) catch |err| switch (err) {
+ error.WouldBlock => return error.Unexpected, // file was not opened as non-blocking
+ error.NotOpenForWriting => return error.Unexpected, // we definitely opened the file for writing
+ else => |e| return e,
+ };
// Ask the filesystem driver to insert extents into the file without copying any data
const last_offset, const last_size = parent.last.location(mf).resolve(mf);
const last_end = last_offset + last_size;
@@ -674,7 +738,7 @@ fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested
enclosing_ni.setLocationAssumeCapacity(mf, enclosing_offset, new_enclosing_size);
if (enclosing_ni == Node.Index.root) {
assert(enclosing_offset == 0);
- try mf.ensureTotalCapacity(@intCast(new_enclosing_size));
+ try mf.ensureTotalCapacityInner(@intCast(new_enclosing_size));
break;
}
var after_ni = enclosing.next;
@@ -865,7 +929,7 @@ fn realignNode(
gpa: std.mem.Allocator,
ni: Node.Index,
new_alignment: std.mem.Alignment,
-) !void {
+) (Allocator.Error || Io.Cancelable || IoError)!void {
assert(ni != Node.Index.root); // currently unsupported
const node = ni.get(mf);
@@ -936,7 +1000,7 @@ fn realignNode(
}
}
-fn moveRange(mf: *MappedFile, old_file_offset: u64, new_file_offset: u64, size: u64) !void {
+fn moveRange(mf: *MappedFile, old_file_offset: u64, new_file_offset: u64, size: u64) (Io.Cancelable || IoError)!void {
// make a copy of this node at the new location
try mf.copyRange(old_file_offset, new_file_offset, size);
// 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:
@memset(mf.memory_map.memory[@intCast(old_file_offset)..][0..@intCast(size)], 0);
}
-fn copyRange(mf: *MappedFile, old_file_offset: u64, new_file_offset: u64, size: u64) !void {
+fn copyRange(mf: *MappedFile, old_file_offset: u64, new_file_offset: u64, size: u64) (Io.Cancelable || IoError)!void {
const copy_size = try mf.copyFileRange(mf.memory_map.file, old_file_offset, new_file_offset, size);
if (copy_size < size) @memcpy(
mf.memory_map.memory[@intCast(new_file_offset + copy_size)..][0..@intCast(size - copy_size)],
@@ -980,9 +1044,13 @@ fn copyFileRange(
old_file_offset: u64,
new_file_offset: u64,
size: u64,
-) !u64 {
+) (Io.Cancelable || IoError)!u64 {
const io = mf.io;
- try mf.memory_map.write(io);
+ mf.memory_map.write(io) catch |err| switch (err) {
+ error.WouldBlock => return error.Unexpected, // file was not opened as non-blocking
+ error.NotOpenForWriting => return error.Unexpected, // we definitely opened the file for writing
+ else => |e| return e,
+ };
var remaining_size = size;
if (is_linux and !mf.flags.copy_file_range_unsupported) {
var old_file_offset_mut: i64 = @intCast(old_file_offset);
@@ -1021,17 +1089,41 @@ fn copyFileRange(
return size - remaining_size;
}
-fn ensureCapacityForSetLocation(mf: *MappedFile, gpa: std.mem.Allocator) !void {
+fn ensureCapacityForSetLocation(mf: *MappedFile, gpa: std.mem.Allocator) Allocator.Error!void {
try mf.large.ensureUnusedCapacity(gpa, 2);
try mf.updates.ensureUnusedCapacity(gpa, 1);
}
-pub fn ensureTotalCapacity(mf: *MappedFile, new_capacity: usize) !void {
+pub fn ensureTotalCapacity(mf: *MappedFile, new_capacity: usize) Error!void {
+ mf.ensureTotalCapacityInner(new_capacity) catch |err| switch (err) {
+ error.OutOfMemory,
+ error.Canceled,
+ => |e| return e,
+
+ else => |e| {
+ mf.io_err = e;
+ return error.MappedFileIo;
+ },
+ };
+}
+fn ensureTotalCapacityInner(mf: *MappedFile, new_capacity: usize) (Allocator.Error || Io.Cancelable || IoError)!void {
if (mf.memory_map.memory.len >= new_capacity) return;
- try mf.ensureTotalCapacityPrecise(new_capacity +| new_capacity / growth_factor);
+ try mf.ensureTotalCapacityPreciseInner(new_capacity +| new_capacity / growth_factor);
}
-pub fn ensureTotalCapacityPrecise(mf: *MappedFile, new_capacity: usize) !void {
+pub fn ensureTotalCapacityPrecise(mf: *MappedFile, new_capacity: usize) Error!void {
+ mf.ensureTotalCapacityPreciseInner(new_capacity) catch |err| switch (err) {
+ error.OutOfMemory,
+ error.Canceled,
+ => |e| return e,
+
+ else => |e| {
+ mf.io_err = e;
+ return error.MappedFileIo;
+ },
+ };
+}
+fn ensureTotalCapacityPreciseInner(mf: *MappedFile, new_capacity: usize) (Allocator.Error || Io.Cancelable || IoError)!void {
if (mf.memory_map.memory.len >= new_capacity) return;
const io = mf.io;
const aligned_capacity = mf.flags.block_size.forward(new_capacity);
@@ -1047,7 +1139,11 @@ pub fn ensureTotalCapacityPrecise(mf: *MappedFile, new_capacity: usize) !void {
}
const file = mf.memory_map.file;
- mf.memory_map = try .create(io, file, .{ .len = aligned_capacity });
+ mf.memory_map = Io.File.MemoryMap.create(io, file, .{ .len = aligned_capacity }) catch |err| switch (err) {
+ error.WouldBlock => return error.Unexpected, // file was not opened as non-blocking
+ error.NotOpenForReading => return error.Unexpected, // we definitely opened the file for writing
+ else => |e| return e,
+ };
}
pub fn unmap(mf: *MappedFile) void {
@@ -1059,9 +1155,22 @@ pub fn unmap(mf: *MappedFile) void {
mf.memory_map.file = file;
}
-pub fn flush(mf: *MappedFile) Io.File.WritePositionalError!void {
- const io = mf.io;
- try mf.memory_map.write(io);
+pub fn flush(mf: *MappedFile) (Io.Cancelable || error{MappedFileIo})!void {
+ mf.memory_map.write(mf.io) catch |err| switch (err) {
+ error.Canceled => |e| return e,
+
+ error.WouldBlock, // file was not opened as non-blocking
+ error.NotOpenForWriting, // we definitely opened the file for writing
+ => {
+ mf.io_err = error.Unexpected;
+ return error.MappedFileIo;
+ },
+
+ else => |e| {
+ mf.io_err = e;
+ return error.MappedFileIo;
+ },
+ };
}
fn verify(mf: *MappedFile) void {
diff --git a/src/link/Queue.zig b/src/link/Queue.zig
@@ -135,7 +135,7 @@ pub fn finishPrelinkQueue(q: *Queue, comp: *Compilation) Io.Cancelable!void {
lf.post_prelink = true;
} else |err| switch (err) {
error.OutOfMemory => comp.link_diags.setAllocFailure(),
- error.LinkFailure => {},
+ error.AlreadyReported => {},
error.Canceled => |e| return e,
}
}
@@ -178,7 +178,7 @@ fn runLinkTasks(q: *Queue, comp: *Compilation) void {
} else |err| switch (err) {
error.OutOfMemory => comp.link_diags.setAllocFailure(),
error.Canceled => @panic("TODO"),
- error.LinkFailure => {},
+ error.AlreadyReported => {},
}
}
}
@@ -205,7 +205,11 @@ fn runIdleTask(comp: *Compilation, tid: Zcu.PerThread.Id) bool {
comp.link_diags.setAllocFailure();
break :have_more false;
},
- error.LinkFailure => false,
+ error.AlreadyReported => false,
+ error.Canceled => {
+ comp.io.recancel();
+ return false;
+ },
};
}
diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig
@@ -140,19 +140,8 @@ fn generate(
};
linker.cg.genNav(do_codegen) catch |err| switch (err) {
- error.CodegenFail => switch (zcu.codegenFailMsg(nav_index, linker.cg.error_msg.?)) {
- error.CodegenFail => {},
- error.OutOfMemory => |e| return e,
- },
- else => |other| {
- // There might be an error that happened *after* linker.error_msg
- // was already allocated, so be sure to free it.
- if (linker.cg.error_msg) |error_msg| {
- error_msg.deinit(gpa);
- }
-
- return other;
- },
+ error.AlreadyReported => return,
+ else => |e| return e,
};
}
@@ -168,7 +157,7 @@ pub fn updateFunc(
try linker.generate(pt, nav, air.*, liveness.*.?, true);
}
-pub fn updateNav(linker: *Linker, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.File.UpdateNavError!void {
+pub fn updateNav(linker: *Linker, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.Error!void {
const ip = &pt.zcu.intern_pool;
log.debug("lowering nav {f}({d})", .{ ip.getNav(nav).fqn.fmt(ip), nav });
try linker.generate(pt, nav, undefined, undefined, false);
@@ -231,7 +220,7 @@ pub fn flush(
arena: Allocator,
tid: Zcu.PerThread.Id,
prog_node: std.Progress.Node,
-) link.File.FlushError!void {
+) link.Error!void {
// The goal is to never use this because it's only needed if we need to
// write to InternPool, but flush is too late to be writing to the
// InternPool.
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig
@@ -568,7 +568,7 @@ pub const SourceLocation = enum(u32) {
err_msg.notes[err.note_slot - 1].source_location = .{ .wasm = sl };
}
- pub fn fail(sl: SourceLocation, diags: *link.Diags, comptime format: []const u8, args: anytype) error{LinkFailure} {
+ pub fn fail(sl: SourceLocation, diags: *link.Diags, comptime format: []const u8, args: anytype) error{AlreadyReported} {
return diags.failSourceLocation(.{ .wasm = sl }, format, args);
}
@@ -3027,12 +3027,12 @@ fn openParseObjectReportingFailure(wasm: *Wasm, path: Path) void {
const diags = &comp.link_diags;
const obj = link.openObject(io, path, false, false) catch |err| {
switch (diags.failParse(path, "failed to open object: {t}", .{err})) {
- error.LinkFailure => return,
+ error.AlreadyReported => return,
}
};
wasm.parseObject(obj) catch |err| {
switch (diags.failParse(path, "failed to parse object: {t}", .{err})) {
- error.LinkFailure => return,
+ error.AlreadyReported => return,
}
};
}
@@ -3336,12 +3336,12 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index
}
}
-pub fn updateLineNumber(wasm: *Wasm, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {
+pub fn updateLineNumber(wasm: *Wasm, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) link.Error!void {
const comp = wasm.base.comp;
const diags = &comp.link_diags;
if (wasm.dwarf) |*dw| {
dw.updateLineNumber(pt.zcu, ti_id) catch |err| switch (err) {
- error.Overflow, error.OutOfMemory => |e| return e,
+ error.OutOfMemory, error.Canceled, error.AlreadyReported => |e| return e,
else => |e| return diags.fail("failed to update dwarf line numbers: {s}", .{@errorName(e)}),
};
}
@@ -3417,7 +3417,7 @@ pub fn loadInput(wasm: *Wasm, input: link.Input) !void {
}
}
-pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!void {
+pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void {
const tracy = trace(@src());
defer tracy.end();
@@ -3526,7 +3526,7 @@ pub fn markFunctionImport(
name: String,
import: *FunctionImport,
func_index: FunctionImport.Index,
-) link.File.FlushError!void {
+) link.Error!void {
// import.flags.alive might be already true from a previous update. In such
// case, we must still run the logic in this function, in case the item
// being marked was reverted by the `flush` logic that resets the hash
@@ -3557,7 +3557,7 @@ pub fn markFunctionImport(
}
/// Recursively mark alive everything referenced by the function.
-fn markFunction(wasm: *Wasm, i: ObjectFunctionIndex, override_export: bool) link.File.FlushError!void {
+fn markFunction(wasm: *Wasm, i: ObjectFunctionIndex, override_export: bool) link.Error!void {
const comp = wasm.base.comp;
const gpa = comp.gpa;
const gop = try wasm.functions.getOrPut(gpa, .fromObjectFunction(wasm, i));
@@ -3590,7 +3590,7 @@ fn markGlobalImport(
name: String,
import: *GlobalImport,
global_index: GlobalImport.Index,
-) link.File.FlushError!void {
+) link.Error!void {
// import.flags.alive might be already true from a previous update. In such
// case, we must still run the logic in this function, in case the item
// being marked was reverted by the `flush` logic that resets the hash
@@ -3630,7 +3630,7 @@ fn markGlobalImport(
}
}
-fn markGlobal(wasm: *Wasm, i: ObjectGlobalIndex, override_export: bool) link.File.FlushError!void {
+fn markGlobal(wasm: *Wasm, i: ObjectGlobalIndex, override_export: bool) link.Error!void {
const comp = wasm.base.comp;
const gpa = comp.gpa;
const gop = try wasm.globals.getOrPut(gpa, .fromObjectGlobal(wasm, i));
@@ -3653,7 +3653,7 @@ fn markTableImport(
name: String,
import: *TableImport,
table_index: TableImport.Index,
-) link.File.FlushError!void {
+) link.Error!void {
if (import.flags.alive) return;
import.flags.alive = true;
@@ -3675,7 +3675,7 @@ fn markTableImport(
}
}
-fn markDataSegment(wasm: *Wasm, segment_index: ObjectDataSegment.Index) link.File.FlushError!void {
+fn markDataSegment(wasm: *Wasm, segment_index: ObjectDataSegment.Index) link.Error!void {
const comp = wasm.base.comp;
const segment = segment_index.ptr(wasm);
if (segment.flags.alive) return;
@@ -3693,7 +3693,7 @@ pub fn markDataImport(
name: String,
import: *ObjectDataImport,
data_index: ObjectDataImport.Index,
-) link.File.FlushError!void {
+) link.Error!void {
if (import.flags.alive) return;
import.flags.alive = true;
@@ -3715,7 +3715,7 @@ pub fn markDataImport(
}
}
-fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.File.FlushError!void {
+fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.Error!void {
const gpa = wasm.base.comp.gpa;
for (relocs.slice.tags(wasm), relocs.slice.pointees(wasm), relocs.slice.offsets(wasm)) |tag, pointee, offset| {
if (offset >= relocs.end) break;
@@ -3812,7 +3812,7 @@ fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.Fil
}
}
-fn markTable(wasm: *Wasm, i: ObjectTableIndex) link.File.FlushError!void {
+fn markTable(wasm: *Wasm, i: ObjectTableIndex) link.Error!void {
try wasm.tables.put(wasm.base.comp.gpa, .fromObjectTable(i), {});
}
@@ -3821,7 +3821,7 @@ pub fn flush(
arena: Allocator,
tid: Zcu.PerThread.Id,
prog_node: std.Progress.Node,
-) link.File.FlushError!void {
+) link.Error!void {
// The goal is to never use this because it's only needed if we need to
// write to InternPool, but flush is too late to be writing to the
// InternPool.
@@ -3864,7 +3864,7 @@ pub fn flush(
try wasm.flush_buffer.data_imports.reinit(gpa, wasm.data_imports.keys(), wasm.data_imports.values());
return wasm.flush_buffer.finish(wasm) catch |err| switch (err) {
- error.OutOfMemory, error.LinkFailure => |e| return e,
+ error.OutOfMemory, error.AlreadyReported => |e| return e,
else => |e| return diags.fail("failed to flush wasm: {s}", .{@errorName(e)}),
};
}
@@ -4275,7 +4275,7 @@ fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !Zcu
{
var aw: std.Io.Writer.Allocating = .fromArrayList(wasm.base.comp.gpa, &wasm.string_bytes);
defer wasm.string_bytes = aw.toArrayList();
- codegen.generateSymbol(&wasm.base, pt, .unneeded, .fromInterned(ip_index), &aw.writer, .none) catch |err| switch (err) {
+ codegen.generateSymbol(&wasm.base, pt, .fromInterned(ip_index), &aw.writer, .none) catch |err| switch (err) {
error.WriteFailed => return error.OutOfMemory,
else => |e| return e,
};
@@ -4349,7 +4349,7 @@ fn resolveFunctionSynthetic(
res: FunctionImport.Resolution,
params: []const std.wasm.Valtype,
returns: []const std.wasm.Valtype,
-) link.File.FlushError!void {
+) link.Error!void {
import.resolution = res;
wasm.functions.putAssumeCapacity(res, {});
// This is not only used for type-checking but also ensures the function
diff --git a/src/link/Wasm/Flush.zig b/src/link/Wasm/Flush.zig
@@ -274,7 +274,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
}
}
- if (diags.hasErrors()) return error.LinkFailure;
+ if (diags.hasErrors()) return error.AlreadyReported;
// Merge indirect function tables.
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 {
if (initial_memory > std.math.maxInt(u32)) {
diags.addError("initial memory value {d} exceeds 32-bit address space", .{initial_memory});
}
- if (diags.hasErrors()) return error.LinkFailure;
+ if (diags.hasErrors()) return error.AlreadyReported;
memory_ptr = initial_memory;
} else {
memory_ptr = mem.alignForward(u64, memory_ptr, std.wasm.page_size);
@@ -535,7 +535,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
if (max_memory > std.math.maxInt(u32)) {
diags.addError("maximum memory value {d} exceeds 32-bit address space", .{max_memory});
}
- if (diags.hasErrors()) return error.LinkFailure;
+ if (diags.hasErrors()) return error.AlreadyReported;
wasm.memories.limits.max = @intCast(max_memory / page_size);
wasm.memories.limits.flags.has_max = true;
if (shared_memory) wasm.memories.limits.flags.is_shared = true;
diff --git a/src/link/Wasm/Object.zig b/src/link/Wasm/Object.zig
@@ -1431,7 +1431,7 @@ fn parseFeatures(
bytes: []const u8,
start_pos: usize,
path: Path,
-) error{ OutOfMemory, LinkFailure }!struct { Wasm.Feature.Set, usize } {
+) error{ OutOfMemory, AlreadyReported }!struct { Wasm.Feature.Set, usize } {
const gpa = wasm.base.comp.gpa;
const diags = &wasm.base.comp.link_diags;
const features_len, var pos = readLeb(u32, bytes, start_pos);
diff --git a/src/register_manager.zig b/src/register_manager.zig
@@ -14,7 +14,7 @@ const link = @import("link.zig");
const log = std.log.scoped(.register_manager);
-pub const AllocationError = @import("codegen.zig").CodeGenError || error{OutOfRegisters};
+pub const AllocationError = @import("codegen.zig").Error || error{OutOfRegisters};
pub fn RegisterManager(
comptime Function: type,