authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-10-08 23:41:39-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-10-09 15:40:59-07:00
logc86a334d43c1818ed19eb403f88e61e38bbf20d6
tree2fdfd31e19d6acb4ee3deb4ee873e10b161cdfb1
parent10cb578e4e16bac44055f277cd06baaf99b159b6

link.Elf.Object.initAtoms: reduce state access and indirection

The initAtoms function now only uses the `elf_file` parameter for reporting linker error messages, making it easier to see that the function has no data dependencies other than the Object struct itself, making it easier to parallelize or otherwise move that logic around. Also removed an indirect call via `addExtra` since we already know the atom's file is the current Object instance. All calls to `Atom.addExtra` should be audited for similar reasons. Also removed unjustified use of `inline fn`.

2 files changed, 32 insertions(+), 21 deletions(-)

src/link/Elf/Atom.zig+11-11
......@@ -868,15 +868,7 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any
868868 if (has_reloc_errors) return error.RelocFailure;
869869}
870870
871const AddExtraOpts = struct {
872 thunk: ?u32 = null,
873 fde_start: ?u32 = null,
874 fde_count: ?u32 = null,
875 rel_index: ?u32 = null,
876 rel_count: ?u32 = null,
877};
878
879pub fn addExtra(atom: *Atom, opts: AddExtraOpts, elf_file: *Elf) void {
871pub fn addExtra(atom: *Atom, opts: Extra.AsOptionals, elf_file: *Elf) void {
880872 const file_ptr = atom.file(elf_file).?;
881873 var extras = file_ptr.atomExtra(atom.extra_index);
882874 inline for (@typeInfo(@TypeOf(opts)).@"struct".fields) |field| {
......@@ -887,11 +879,11 @@ pub fn addExtra(atom: *Atom, opts: AddExtraOpts, elf_file: *Elf) void {
887879 file_ptr.setAtomExtra(atom.extra_index, extras);
888880}
889881
890pub inline fn extra(atom: Atom, elf_file: *Elf) Extra {
882pub fn extra(atom: Atom, elf_file: *Elf) Extra {
891883 return atom.file(elf_file).?.atomExtra(atom.extra_index);
892884}
893885
894pub inline fn setExtra(atom: Atom, extras: Extra, elf_file: *Elf) void {
886pub fn setExtra(atom: Atom, extras: Extra, elf_file: *Elf) void {
895887 atom.file(elf_file).?.setAtomExtra(atom.extra_index, extras);
896888}
897889
......@@ -2103,6 +2095,14 @@ pub const Extra = struct {
21032095
21042096 /// Count of relocations belonging to this atom.
21052097 rel_count: u32 = 0,
2098
2099 pub const AsOptionals = struct {
2100 thunk: ?u32 = null,
2101 fde_start: ?u32 = null,
2102 fde_count: ?u32 = null,
2103 rel_index: ?u32 = null,
2104 rel_count: ?u32 = null,
2105 };
21062106};
21072107
21082108const std = @import("std");
src/link/Elf/Object.zig+21-10
......@@ -166,6 +166,9 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil
166166}
167167
168168fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file: *Elf) !void {
169 const comp = elf_file.base.comp;
170 const debug_fmt_strip = comp.config.debug_format == .strip;
171 const target = comp.root_mod.resolved_target.result;
169172 const shdrs = self.shdrs.items;
170173 try self.atoms.ensureTotalCapacityPrecise(allocator, shdrs.len);
171174 try self.atoms_extra.ensureTotalCapacityPrecise(allocator, shdrs.len * @sizeOf(Atom.Extra));
......@@ -194,7 +197,7 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file:
194197 break :blk group_info_sym.st_name;
195198 };
196199
197 const shndx = @as(u32, @intCast(i));
200 const shndx: u32 = @intCast(i);
198201 const group_raw_data = try self.preadShdrContentsAlloc(allocator, handle, shndx);
199202 defer allocator.free(group_raw_data);
200203 const group_nmembers = math.divExact(usize, group_raw_data.len, @sizeOf(u32)) catch {
......@@ -209,7 +212,7 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file:
209212 return elf_file.failFile(self.index, "corrupt section group: unknown SHT_GROUP format", .{});
210213 }
211214
212 const group_start = @as(u32, @intCast(self.comdat_group_data.items.len));
215 const group_start: u32 = @intCast(self.comdat_group_data.items.len);
213216 try self.comdat_group_data.appendUnalignedSlice(allocator, group_members[1..]);
214217
215218 const comdat_group_index = try self.addComdatGroup(allocator);
......@@ -233,8 +236,8 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file:
233236 => {},
234237
235238 else => {
236 const shndx = @as(u32, @intCast(i));
237 if (self.skipShdr(shndx, elf_file)) continue;
239 const shndx: u32 = @intCast(i);
240 if (self.skipShdr(shndx, debug_fmt_strip)) continue;
238241 const size, const alignment = if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) blk: {
239242 const data = try self.preadShdrContentsAlloc(allocator, handle, shndx);
240243 defer allocator.free(data);
......@@ -262,9 +265,9 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file:
262265 atom_ptr.relocs_section_index = @intCast(i);
263266 const rel_index: u32 = @intCast(self.relocs.items.len);
264267 const rel_count: u32 = @intCast(relocs.len);
265 atom_ptr.addExtra(.{ .rel_index = rel_index, .rel_count = rel_count }, elf_file);
268 self.setAtomFields(atom_ptr, .{ .rel_index = rel_index, .rel_count = rel_count });
266269 try self.relocs.appendUnalignedSlice(allocator, relocs);
267 if (elf_file.getTarget().cpu.arch == .riscv64) {
270 if (target.cpu.arch == .riscv64) {
268271 sortRelocs(self.relocs.items[rel_index..][0..rel_count]);
269272 }
270273 }
......@@ -273,15 +276,14 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file:
273276 };
274277}
275278
276fn skipShdr(self: *Object, index: u32, elf_file: *Elf) bool {
277 const comp = elf_file.base.comp;
279fn skipShdr(self: *Object, index: u32, debug_fmt_strip: bool) bool {
278280 const shdr = self.shdrs.items[index];
279281 const name = self.getString(shdr.sh_name);
280282 const ignore = blk: {
281283 if (mem.startsWith(u8, name, ".note")) break :blk true;
282284 if (mem.startsWith(u8, name, ".llvm_addrsig")) break :blk true;
283285 if (mem.startsWith(u8, name, ".riscv.attributes")) break :blk true; // TODO: riscv attributes
284 if (comp.config.debug_format == .strip and shdr.sh_flags & elf.SHF_ALLOC == 0 and
286 if (debug_fmt_strip and shdr.sh_flags & elf.SHF_ALLOC == 0 and
285287 mem.startsWith(u8, name, ".debug")) break :blk true;
286288 break :blk false;
287289 };
......@@ -1257,7 +1259,7 @@ pub fn addAtomExtra(self: *Object, allocator: Allocator, extra: Atom.Extra) !u32
12571259}
12581260
12591261pub fn addAtomExtraAssumeCapacity(self: *Object, extra: Atom.Extra) u32 {
1260 const index = @as(u32, @intCast(self.atoms_extra.items.len));
1262 const index: u32 = @intCast(self.atoms_extra.items.len);
12611263 const fields = @typeInfo(Atom.Extra).@"struct".fields;
12621264 inline for (fields) |field| {
12631265 self.atoms_extra.appendAssumeCapacity(switch (field.type) {
......@@ -1292,6 +1294,15 @@ pub fn setAtomExtra(self: *Object, index: u32, extra: Atom.Extra) void {
12921294 }
12931295}
12941296
1297fn setAtomFields(o: *Object, atom_ptr: *Atom, opts: Atom.Extra.AsOptionals) void {
1298 assert(o.index == atom_ptr.file_index);
1299 var extras = o.atomExtra(atom_ptr.extra_index);
1300 inline for (@typeInfo(@TypeOf(opts)).@"struct".fields) |field| {
1301 if (@field(opts, field.name)) |x| @field(extras, field.name) = x;
1302 }
1303 o.setAtomExtra(atom_ptr.extra_index, extras);
1304}
1305
12951306fn addInputMergeSection(self: *Object, allocator: Allocator) !InputMergeSection.Index {
12961307 const index: InputMergeSection.Index = @intCast(self.input_merge_sections.items.len);
12971308 const msec = try self.input_merge_sections.addOne(allocator);