Commit da25ed95fc
Changed files (7)
src/link/Elf/relocatable.zig
@@ -1,4 +1,4 @@
-pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) link.File.FlushError!void {
+pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {
const gpa = comp.gpa;
const diags = &comp.link_diags;
@@ -130,7 +130,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) link.File.FlushError!v
if (diags.hasErrors()) return error.LinkFailure;
}
-pub fn flushObject(elf_file: *Elf, comp: *Compilation) link.File.FlushError!void {
+pub fn flushObject(elf_file: *Elf, comp: *Compilation) !void {
const diags = &comp.link_diags;
if (diags.hasErrors()) return error.LinkFailure;
@@ -259,7 +259,7 @@ fn initComdatGroups(elf_file: *Elf) !void {
}
}
-fn updateSectionSizes(elf_file: *Elf) link.File.FlushError!void {
+fn updateSectionSizes(elf_file: *Elf) !void {
const slice = elf_file.sections.slice();
for (slice.items(.atom_list_2)) |*atom_list| {
if (atom_list.atoms.keys().len == 0) continue;
src/link/Elf/ZigObject.zig
@@ -264,7 +264,7 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {
}
}
-pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) link.File.FlushError!void {
+pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void {
// Handle any lazy symbols that were emitted by incremental compilation.
if (self.lazy_syms.getPtr(.anyerror_type)) |metadata| {
const pt: Zcu.PerThread = .activate(elf_file.base.comp.zcu.?, tid);
@@ -279,7 +279,7 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) link.File.
metadata.text_symbol_index,
) catch |err| return switch (err) {
error.CodegenFail => error.LinkFailure,
- else => |e| e,
+ else => |e| return e,
};
if (metadata.rodata_state != .unused) self.updateLazySymbol(
elf_file,
@@ -288,7 +288,7 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) link.File.
metadata.rodata_symbol_index,
) catch |err| return switch (err) {
error.CodegenFail => error.LinkFailure,
- else => |e| e,
+ else => |e| return e,
};
}
for (self.lazy_syms.values()) |*metadata| {
@@ -1263,7 +1263,7 @@ fn updateNavCode(
shdr_index: u32,
code: []const u8,
stt_bits: u8,
-) !void {
+) link.File.UpdateNavError!void {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const ip = &zcu.intern_pool;
@@ -1342,7 +1342,7 @@ fn updateNavCode(
const shdr = elf_file.sections.items(.shdr)[shdr_index];
if (shdr.sh_type != elf.SHT_NOBITS) {
const file_offset = atom_ptr.offset(elf_file);
- try elf_file.base.file.?.pwriteAll(code, file_offset);
+ try elf_file.pwriteAll(code, file_offset);
log.debug("writing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), file_offset, file_offset + code.len });
}
}
@@ -1355,7 +1355,7 @@ fn updateTlv(
sym_index: Symbol.Index,
shndx: u32,
code: []const u8,
-) !void {
+) link.File.UpdateNavError!void {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
const gpa = zcu.gpa;
@@ -1394,7 +1394,7 @@ fn updateTlv(
const shdr = elf_file.sections.items(.shdr)[shndx];
if (shdr.sh_type != elf.SHT_NOBITS) {
const file_offset = atom_ptr.offset(elf_file);
- try elf_file.base.file.?.pwriteAll(code, file_offset);
+ try elf_file.pwriteAll(code, file_offset);
log.debug("writing TLV {s} from 0x{x} to 0x{x}", .{
atom_ptr.name(elf_file),
file_offset,
@@ -1617,7 +1617,7 @@ fn updateLazySymbol(
pt: Zcu.PerThread,
sym: link.File.LazySymbol,
symbol_index: Symbol.Index,
-) link.File.FlushError!void {
+) !void {
const zcu = pt.zcu;
const gpa = zcu.gpa;
@@ -1698,7 +1698,7 @@ fn updateLazySymbol(
local_sym.value = 0;
local_esym.st_value = 0;
- try elf_file.base.file.?.pwriteAll(code, atom_ptr.offset(elf_file));
+ try elf_file.pwriteAll(code, atom_ptr.offset(elf_file));
}
const LowerConstResult = union(enum) {
@@ -1750,7 +1750,7 @@ fn lowerConst(
try self.allocateAtom(atom_ptr, true, elf_file);
errdefer self.freeNavMetadata(elf_file, sym_index);
- try elf_file.base.file.?.pwriteAll(code, atom_ptr.offset(elf_file));
+ try elf_file.pwriteAll(code, atom_ptr.offset(elf_file));
return .{ .ok = sym_index };
}
@@ -1898,7 +1898,7 @@ fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) u64 {
return len;
}
-fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void {
+fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) link.File.UpdateNavError!void {
const atom_ptr = tr_sym.atom(elf_file).?;
const fileoff = atom_ptr.offset(elf_file);
const source_addr = tr_sym.address(.{}, elf_file);
@@ -1908,7 +1908,7 @@ fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void {
.x86_64 => try x86_64.writeTrampolineCode(source_addr, target_addr, &buf),
else => @panic("TODO implement write trampoline for this CPU arch"),
};
- try elf_file.base.file.?.pwriteAll(out, fileoff);
+ try elf_file.pwriteAll(out, fileoff);
if (elf_file.base.child_pid) |pid| {
switch (builtin.os.tag) {
src/link/MachO/ZigObject.zig
@@ -559,18 +559,26 @@ pub fn flushModule(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id)
// Most lazy symbols can be updated on first use, but
// anyerror needs to wait for everything to be flushed.
- if (metadata.text_state != .unused) try self.updateLazySymbol(
+ if (metadata.text_state != .unused) self.updateLazySymbol(
macho_file,
pt,
.{ .kind = .code, .ty = .anyerror_type },
metadata.text_symbol_index,
- );
- if (metadata.const_state != .unused) try self.updateLazySymbol(
+ ) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ error.LinkFailure => return error.LinkFailure,
+ else => |e| return diags.fail("failed to update lazy symbol: {s}", .{@errorName(e)}),
+ };
+ if (metadata.const_state != .unused) self.updateLazySymbol(
macho_file,
pt,
.{ .kind = .const_data, .ty = .anyerror_type },
metadata.const_symbol_index,
- );
+ ) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ error.LinkFailure => return error.LinkFailure,
+ else => |e| return diags.fail("failed to update lazy symbol: {s}", .{@errorName(e)}),
+ };
}
for (self.lazy_syms.values()) |*metadata| {
if (metadata.text_state != .unused) metadata.text_state = .flushed;
@@ -803,7 +811,7 @@ pub fn updateFunc(
.ok => code_buffer.items,
.fail => |em| {
try zcu.failed_codegen.put(gpa, func.owner_nav, em);
- return;
+ return error.CodegenFail;
},
};
@@ -855,7 +863,8 @@ pub fn updateFunc(
}
const target_sym = self.symbols.items[sym_index];
const source_sym = self.symbols.items[target_sym.getExtra(macho_file).trampoline];
- try writeTrampoline(source_sym, target_sym, macho_file);
+ writeTrampoline(source_sym, target_sym, macho_file) catch |err|
+ return macho_file.base.cgFail(func.owner_nav, "failed to write trampoline: {s}", .{@errorName(err)});
}
}
@@ -955,7 +964,6 @@ fn updateNavCode(
else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
};
- const diags = &macho_file.base.comp.link_diags;
const sect = &macho_file.sections.items(.header)[sect_index];
const sym = &self.symbols.items[sym_index];
const nlist = &self.symtab.items(.nlist)[sym.nlist_idx];
@@ -984,7 +992,8 @@ fn updateNavCode(
const need_realloc = code.len > capacity or !required_alignment.check(atom.value);
if (need_realloc) {
- atom.grow(macho_file) catch |err| return diags.fail("failed to grow atom: {s}", .{@errorName(err)});
+ atom.grow(macho_file) catch |err|
+ return macho_file.base.cgFail(nav_index, "failed to grow atom: {s}", .{@errorName(err)});
log.debug("growing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), old_vaddr, atom.value });
if (old_vaddr != atom.value) {
sym.value = 0;
@@ -997,7 +1006,8 @@ fn updateNavCode(
sect.size = needed_size;
}
} else {
- try atom.allocate(macho_file);
+ atom.allocate(macho_file) catch |err|
+ return macho_file.base.cgFail(nav_index, "failed to allocate atom: {s}", .{@errorName(err)});
errdefer self.freeNavMetadata(macho_file, sym_index);
sym.value = 0;
@@ -1006,7 +1016,8 @@ fn updateNavCode(
if (!sect.isZerofill()) {
const file_offset = sect.offset + atom.value;
- try macho_file.pwriteAll(code, file_offset);
+ macho_file.base.file.?.pwriteAll(code, file_offset) catch |err|
+ return macho_file.base.cgFail(nav_index, "failed to write output file: {s}", .{@errorName(err)});
}
}
@@ -1353,7 +1364,7 @@ fn updateLazySymbol(
pt: Zcu.PerThread,
lazy_sym: link.File.LazySymbol,
symbol_index: Symbol.Index,
-) error{ OutOfMemory, LinkFailure }!void {
+) !void {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const diags = &macho_file.base.comp.link_diags;
@@ -1494,7 +1505,7 @@ fn writeTrampoline(tr_sym: Symbol, target: Symbol, macho_file: *MachO) !void {
.x86_64 => try x86_64.writeTrampolineCode(source_addr, target_addr, &buf),
else => @panic("TODO implement write trampoline for this CPU arch"),
};
- try macho_file.pwriteAll(out, fileoff);
+ try macho_file.base.file.?.pwriteAll(out, fileoff);
}
pub fn getOrCreateMetadataForNav(
src/link/Dwarf.zig
@@ -26,9 +26,7 @@ pub const UpdateError = error{
OutOfMemory,
};
-pub const FlushError =
- UpdateError ||
- std.process.GetCwdError;
+pub const FlushError = UpdateError || std.process.GetCwdError;
pub const RelocError =
std.fs.File.PWriteError;
@@ -4312,7 +4310,7 @@ fn refAbbrevCode(dwarf: *Dwarf, abbrev_code: AbbrevCode) UpdateError!@typeInfo(A
return @intFromEnum(abbrev_code);
}
-pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
+pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) !void {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
src/link/Elf.zig
@@ -807,7 +807,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
defer tracy.end();
const comp = self.base.comp;
- const gpa = comp.gpa;
const diags = &comp.link_diags;
if (self.llvm_object) |llvm_object| {
@@ -821,6 +820,18 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
const sub_prog_node = prog_node.start("ELF Flush", 0);
defer sub_prog_node.end();
+ return flushModuleInner(self, arena, tid) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ error.LinkFailure => return error.LinkFailure,
+ else => |e| return diags.fail("ELF flush failed: {s}", .{@errorName(e)}),
+ };
+}
+
+fn flushModuleInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
+ const comp = self.base.comp;
+ const gpa = comp.gpa;
+ const diags = &comp.link_diags;
+
const module_obj_path: ?Path = if (self.base.zcu_object_sub_path) |path| .{
.root_dir = self.base.emit.root_dir,
.sub_path = if (fs.path.dirname(self.base.emit.sub_path)) |dirname|
@@ -2432,7 +2443,7 @@ pub fn addCommentString(self: *Elf) !void {
self.comment_merge_section_index = msec_index;
}
-pub fn resolveMergeSections(self: *Elf) link.File.FlushError!void {
+pub fn resolveMergeSections(self: *Elf) !void {
const tracy = trace(@src());
defer tracy.end();
src/link/MachO.zig
@@ -3423,7 +3423,7 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
};
}
-pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) error{ OutOfMemory, LinkFailure }!void {
+pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) !void {
if (self.base.isRelocatable()) {
try self.growSectionRelocatable(sect_index, needed_size);
} else {
@@ -3431,7 +3431,7 @@ pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) error{ OutOfM
}
}
-fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) error{ OutOfMemory, LinkFailure }!void {
+fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !void {
const diags = &self.base.comp.link_diags;
const sect = &self.sections.items(.header)[sect_index];
@@ -3480,7 +3480,7 @@ fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) err
seg.vmsize = needed_size;
}
-fn growSectionRelocatable(self: *MachO, sect_index: u8, needed_size: u64) error{ OutOfMemory, LinkFailure }!void {
+fn growSectionRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !void {
const sect = &self.sections.items(.header)[sect_index];
if (!sect.isZerofill()) {
@@ -3490,7 +3490,7 @@ fn growSectionRelocatable(self: *MachO, sect_index: u8, needed_size: u64) error{
sect.size = 0;
// Must move the entire section.
- const alignment = try self.alignPow(sect.@"align");
+ const alignment = try math.powi(u32, 2, sect.@"align");
const new_offset = try self.findFreeSpace(needed_size, alignment);
const new_addr = self.findFreeSpaceVirtual(needed_size, alignment);
src/link.zig
@@ -632,15 +632,14 @@ pub const File = struct {
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 = error{
Overflow,
OutOfMemory,
/// Indicates the error is already reported and stored in
/// `failed_codegen` on the Zcu.
CodegenFail,
- /// Indicates the error is already reported and stored in `link_diags`
- /// on the Compilation.
- LinkFailure,
};
/// Called from within CodeGen to retrieve the symbol index of a global symbol.
@@ -1284,6 +1283,20 @@ pub const File = struct {
}, llvm_object, prog_node);
}
+ pub fn cgFail(
+ base: *File,
+ nav_index: InternPool.Nav.Index,
+ comptime format: []const u8,
+ args: anytype,
+ ) error{ CodegenFail, OutOfMemory } {
+ @branchHint(.cold);
+ const zcu = base.comp.zcu.?;
+ const gpa = zcu.gpa;
+ try zcu.failed_codegen.ensureUnusedCapacity(gpa, 1);
+ const msg = try Zcu.ErrorMsg.create(gpa, zcu.navSrcLoc(nav_index), format, args);
+ zcu.failed_codegen.putAssumeCapacityNoClobber(gpa, nav_index, msg);
+ }
+
pub const C = @import("link/C.zig");
pub const Coff = @import("link/Coff.zig");
pub const Plan9 = @import("link/Plan9.zig");