authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-10 16:28:00+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-18 09:13:08+02:00
log5b4c0cc1f9c4cb047064cffb70bc649b83681814
tree596178ec6c3d67e1e55c206ea197a2cee56fd821
parentf8b5466aef4131821b259aa5f0d6b9654a5595ce

macho: update ZigObject to use new ownership model


6 files changed, 321 insertions(+), 201 deletions(-)

src/arch/x86_64/Emit.zig+8-8
......@@ -51,12 +51,12 @@ pub fn emitMir(emit: *Emit) Error!void {
5151 });
5252 } else if (emit.lower.bin_file.cast(link.File.MachO)) |macho_file| {
5353 // Add relocation to the decl.
54 const atom = macho_file.getSymbol(symbol.atom_index).getAtom(macho_file).?;
55 const sym_index = macho_file.getZigObject().?.symbols.items[symbol.sym_index];
54 const zo = macho_file.getZigObject().?;
55 const atom = zo.symbols.items[symbol.atom_index].getAtom(macho_file).?;
5656 try atom.addReloc(macho_file, .{
5757 .tag = .@"extern",
5858 .offset = end_offset - 4,
59 .target = sym_index,
59 .target = symbol.sym_index,
6060 .addend = 0,
6161 .type = .branch,
6262 .meta = .{
......@@ -160,11 +160,11 @@ pub fn emitMir(emit: *Emit) Error!void {
160160 .Obj => true,
161161 .Lib => emit.lower.link_mode == .static,
162162 };
163 const atom = macho_file.getSymbol(data.atom_index).getAtom(macho_file).?;
164 const sym_index = macho_file.getZigObject().?.symbols.items[data.sym_index];
165 const sym = macho_file.getSymbol(sym_index);
163 const zo = macho_file.getZigObject().?;
164 const atom = zo.symbols.items[data.atom_index].getAtom(macho_file).?;
165 const sym = zo.symbols.items[data.sym_index];
166166 if (sym.flags.needs_zig_got and !is_obj_or_static_lib) {
167 _ = try sym.getOrCreateZigGotEntry(sym_index, macho_file);
167 _ = try sym.getOrCreateZigGotEntry(data.sym_index, macho_file);
168168 }
169169 const @"type": link.File.MachO.Relocation.Type = if (sym.flags.needs_zig_got and !is_obj_or_static_lib)
170170 .zig_got_load
......@@ -179,7 +179,7 @@ pub fn emitMir(emit: *Emit) Error!void {
179179 try atom.addReloc(macho_file, .{
180180 .tag = .@"extern",
181181 .offset = @intCast(end_offset - 4),
182 .target = sym_index,
182 .target = data.sym_index,
183183 .addend = 0,
184184 .type = @"type",
185185 .meta = .{
src/arch/x86_64/Lower.zig+2-2
......@@ -425,8 +425,8 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
425425 else => unreachable,
426426 };
427427 } else if (lower.bin_file.cast(link.File.MachO)) |macho_file| {
428 const sym_index = macho_file.getZigObject().?.symbols.items[sym.sym_index];
429 const macho_sym = macho_file.getSymbol(sym_index);
428 const zo = macho_file.getZigObject().?;
429 const macho_sym = zo.symbols.items[sym.sym_index];
430430
431431 if (macho_sym.flags.tlv) {
432432 _ = lower.reloc(.{ .linker_reloc = sym });
src/codegen.zig+5-4
......@@ -901,15 +901,16 @@ fn genDeclRef(
901901 }
902902 return GenResult.mcv(.{ .load_symbol = sym.esym_index });
903903 } else if (lf.cast(link.File.MachO)) |macho_file| {
904 const zo = macho_file.getZigObject().?;
904905 if (is_extern) {
905906 const name = decl.name.toSlice(ip);
906907 const lib_name = if (decl.getOwnedVariable(zcu)) |ov| ov.lib_name.toSlice(ip) else null;
907908 const sym_index = try macho_file.getGlobalSymbol(name, lib_name);
908 macho_file.getSymbol(macho_file.getZigObject().?.symbols.items[sym_index]).flags.needs_got = true;
909 zo.symbols.items[sym_index].flags.needs_got = true;
909910 return GenResult.mcv(.{ .load_symbol = sym_index });
910911 }
911 const sym_index = try macho_file.getZigObject().?.getOrCreateMetadataForDecl(macho_file, decl_index);
912 const sym = macho_file.getSymbol(sym_index);
912 const sym_index = try zo.getOrCreateMetadataForDecl(macho_file, decl_index);
913 const sym = zo.symbols.items[sym_index];
913914 if (is_threadlocal) {
914915 return GenResult.mcv(.{ .load_tlv = sym.nlist_idx });
915916 }
......@@ -956,7 +957,7 @@ fn genUnnamedConst(
956957 },
957958 .macho => {
958959 const macho_file = lf.cast(link.File.MachO).?;
959 const local = macho_file.getSymbol(local_sym_index);
960 const local = macho_file.getZigObject().?.symbols.items[local_sym_index];
960961 return GenResult.mcv(.{ .load_symbol = local.nlist_idx });
961962 },
962963 .coff => {
src/link/MachO.zig+13-9
......@@ -290,8 +290,10 @@ pub fn deinit(self: *MachO) void {
290290 self.dylibs.deinit(gpa);
291291
292292 self.segments.deinit(gpa);
293 for (self.sections.items(.atoms)) |*list| {
294 list.deinit(gpa);
293 for (self.sections.items(.atoms), self.sections.items(.out), self.sections.items(.thunks)) |*atoms, *out, *thnks| {
294 atoms.deinit(gpa);
295 out.deinit(gpa);
296 thnks.deinit(gpa);
295297 }
296298 self.sections.deinit(gpa);
297299
......@@ -561,8 +563,8 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n
561563 if (self.getZigObject()) |zo| {
562564 var has_resolve_error = false;
563565
564 for (zo.atoms.items) |atom_index| {
565 const atom = self.getAtom(atom_index) orelse continue;
566 for (zo.getAtoms()) |atom_index| {
567 const atom = zo.getAtom(atom_index) orelse continue;
566568 if (!atom.flags.alive) continue;
567569 const sect = &self.sections.items(.header)[atom.out_n_sect];
568570 if (sect.isZerofill()) continue;
......@@ -573,7 +575,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n
573575 const atom_size = math.cast(usize, atom.size) orelse return error.Overflow;
574576 const code = try gpa.alloc(u8, atom_size);
575577 defer gpa.free(code);
576 atom.getData(self, code) catch |err| switch (err) {
578 zo.getAtomData(self, atom.*, code) catch |err| switch (err) {
577579 error.InputOutput => {
578580 try self.reportUnexpectedError("fetching code for '{s}' failed", .{
579581 atom.getName(self),
......@@ -1524,7 +1526,7 @@ fn scanRelocs(self: *MachO) !void {
15241526 try self.getFile(index).?.object.scanRelocs(self);
15251527 }
15261528 if (self.getInternalObject()) |obj| {
1527 try obj.scanRelocs(self);
1529 obj.scanRelocs(self);
15281530 }
15291531
15301532 try self.reportUndefs();
......@@ -2394,7 +2396,7 @@ fn writeSectionsAndUpdateLinkeditSizes(self: *MachO) !void {
23942396 self.objc_stubs_sect_index,
23952397 }) |maybe_sect_id| {
23962398 if (maybe_sect_id) |sect_id| {
2397 const out = &slice.items(.out)[sect_id];
2399 const out = slice.items(.out)[sect_id].items;
23982400 try self.writeSyntheticSection(sect_id, out);
23992401 }
24002402 }
......@@ -3970,9 +3972,11 @@ pub const base_tag: link.File.Tag = link.File.Tag.macho;
39703972const Section = struct {
39713973 header: macho.section_64,
39723974 segment_id: u8,
3973 atoms: std.ArrayListUnmanaged(Atom.Index) = .{},
3975 atoms: std.ArrayListUnmanaged(Ref) = .{},
39743976 free_list: std.ArrayListUnmanaged(Atom.Index) = .{},
39753977 last_atom_index: Atom.Index = 0,
3978 thunks: std.ArrayListUnmanaged(Thunk.Index) = .{},
3979 out: std.ArrayListUnmanaged(u8) = .{},
39763980};
39773981
39783982pub const LiteralPool = struct {
......@@ -4018,7 +4022,7 @@ pub const LiteralPool = struct {
40184022 return .{
40194023 .found_existing = gop.found_existing,
40204024 .index = @intCast(gop.index),
4021 .atom = &lp.values.items[gop.index],
4025 .ref = &lp.values.items[gop.index],
40224026 };
40234027 }
40244028
src/link/MachO/Atom.zig-2
......@@ -423,7 +423,6 @@ pub fn addReloc(self: *Atom, macho_file: *MachO, reloc: Relocation) !void {
423423 const gpa = macho_file.base.comp.gpa;
424424 const file = self.getFile(macho_file);
425425 assert(file == .zig_object);
426 assert(self.flags.relocs);
427426 var extra = self.getExtra(macho_file).?;
428427 const rels = &file.zig_object.relocs.items[extra.rel_index];
429428 try rels.append(gpa, reloc);
......@@ -432,7 +431,6 @@ pub fn addReloc(self: *Atom, macho_file: *MachO, reloc: Relocation) !void {
432431}
433432
434433pub fn freeRelocs(self: *Atom, macho_file: *MachO) void {
435 if (!self.flags.relocs) return;
436434 self.getFile(macho_file).zig_object.freeAtomRelocs(self.*, macho_file);
437435 var extra = self.getExtra(macho_file).?;
438436 extra.rel_count = 0;
src/link/MachO/ZigObject.zig+293-176
......@@ -6,9 +6,15 @@ index: File.Index,
66symtab: std.MultiArrayList(Nlist) = .{},
77strtab: StringTable = .{},
88
9symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
10atoms: std.ArrayListUnmanaged(Atom.Index) = .{},
11globals_lookup: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{},
9symbols: std.ArrayListUnmanaged(Symbol) = .{},
10symbols_extra: std.ArrayListUnmanaged(u32) = .{},
11globals: std.ArrayListUnmanaged(MachO.SymbolResolver.Index) = .{},
12/// Maps string index (so name) into nlist index for the global symbol defined within this
13/// module.
14globals_lookup: std.AutoHashMapUnmanaged(u32, u32) = .{},
15atoms: std.ArrayListUnmanaged(Atom) = .{},
16atoms_indexes: std.ArrayListUnmanaged(Atom.Index) = .{},
17atoms_extra: std.ArrayListUnmanaged(u32) = .{},
1218
1319/// Table of tracked LazySymbols.
1420lazy_syms: LazySymbolTable = .{},
......@@ -58,10 +64,13 @@ debug_info_header_dirty: bool = false,
5864debug_line_header_dirty: bool = false,
5965
6066pub fn init(self: *ZigObject, macho_file: *MachO) !void {
67 const tracy = trace(@src());
68 defer tracy.end();
69
6170 const comp = macho_file.base.comp;
6271 const gpa = comp.gpa;
6372
64 try self.atoms.append(gpa, 0); // null input section
73 try self.atoms.append(gpa, .{ .extra = try self.addAtomExtra(gpa, .{}) }); // null input section
6574 try self.strtab.buffer.append(gpa, 0);
6675
6776 switch (comp.config.debug_format) {
......@@ -84,8 +93,12 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {
8493 self.symtab.deinit(allocator);
8594 self.strtab.deinit(allocator);
8695 self.symbols.deinit(allocator);
87 self.atoms.deinit(allocator);
96 self.symbols_extra.deinit(allocator);
97 self.globals.deinit(allocator);
8898 self.globals_lookup.deinit(allocator);
99 self.atoms.deinit(allocator);
100 self.atoms_indexes.deinit(allocator);
101 self.atoms_extra.deinit(allocator);
89102
90103 {
91104 var it = self.decls.iterator();
......@@ -139,32 +152,21 @@ fn addNlist(self: *ZigObject, allocator: Allocator) !Symbol.Index {
139152 return index;
140153}
141154
142pub fn addAtom(self: *ZigObject, macho_file: *MachO) !Symbol.Index {
143 const gpa = macho_file.base.comp.gpa;
144 const atom_index = try macho_file.addAtom();
145 const symbol_index = try macho_file.addSymbol();
146 const nlist_index = try self.addNlist(gpa);
147
148 try self.atoms.append(gpa, atom_index);
149 try self.symbols.append(gpa, symbol_index);
150
151 const atom = macho_file.getAtom(atom_index).?;
152 atom.file = self.index;
153 atom.atom_index = atom_index;
154
155 const symbol = macho_file.getSymbol(symbol_index);
156 symbol.file = self.index;
157 symbol.atom = atom_index;
158
155pub fn createAtomForDecl(self: *ZigObject, allocator: Allocator, macho_file: *MachO) !Symbol.Index {
156 const atom_index = try self.addAtom(allocator);
157 const symbol_index = try self.addSymbol(allocator);
158 const nlist_index = try self.addNlist(allocator);
159159 self.symtab.items(.atom)[nlist_index] = atom_index;
160 try self.atoms_indexes.append(allocator, atom_index);
161 const symbol = &self.symbols.items[symbol_index];
162 symbol.atom_ref = .{ .index = atom_index, .file = self.index };
160163 symbol.nlist_idx = nlist_index;
161
164 symbol.extra = try self.addSymbolExtra(allocator, .{});
162165 const relocs_index = @as(u32, @intCast(self.relocs.items.len));
163 const relocs = try self.relocs.addOne(gpa);
166 const relocs = try self.relocs.addOne(allocator);
164167 relocs.* = .{};
165 try atom.addExtra(.{ .rel_index = relocs_index, .rel_count = 0 }, macho_file);
166 atom.flags.relocs = true;
167
168 const atom = self.getAtom(atom_index).?;
169 atom.addExtra(.{ .rel_index = relocs_index, .rel_count = 0 }, macho_file);
168170 return symbol_index;
169171}
170172
......@@ -191,89 +193,51 @@ pub fn getAtomData(self: ZigObject, macho_file: *MachO, atom: Atom, buffer: []u8
191193}
192194
193195pub fn getAtomRelocs(self: *ZigObject, atom: Atom, macho_file: *MachO) []const Relocation {
194 if (!atom.flags.relocs) return &[0]Relocation{};
195 const extra = atom.getExtra(macho_file).?;
196 const extra = atom.getExtra(macho_file);
196197 const relocs = self.relocs.items[extra.rel_index];
197198 return relocs.items[0..extra.rel_count];
198199}
199200
200201pub fn freeAtomRelocs(self: *ZigObject, atom: Atom, macho_file: *MachO) void {
201 if (atom.flags.relocs) {
202 const extra = atom.getExtra(macho_file).?;
203 self.relocs.items[extra.rel_index].clearRetainingCapacity();
204 }
202 const extra = atom.getExtra(macho_file);
203 self.relocs.items[extra.rel_index].clearRetainingCapacity();
205204}
206205
207pub fn resolveSymbols(self: *ZigObject, macho_file: *MachO) void {
206pub fn resolveSymbols(self: *ZigObject, macho_file: *MachO) !void {
208207 const tracy = trace(@src());
209208 defer tracy.end();
210209
211 for (self.symbols.items, 0..) |index, i| {
212 const nlist_idx = @as(Symbol.Index, @intCast(i));
213 const nlist = self.symtab.items(.nlist)[nlist_idx];
214 const atom_index = self.symtab.items(.atom)[nlist_idx];
210 const gpa = macho_file.base.comp.gpa;
215211
212 for (self.symtab.items(.nlist), self.symtab.items(.atom), self.globals.items, 0..) |nlist, atom_index, *global, i| {
216213 if (!nlist.ext()) continue;
217 if (nlist.undf() and !nlist.tentative()) continue;
218214 if (nlist.sect()) {
219 const atom = macho_file.getAtom(atom_index).?;
215 const atom = self.getAtom(atom_index).?;
220216 if (!atom.flags.alive) continue;
221217 }
222218
223 const symbol = macho_file.getSymbol(index);
219 const gop = try macho_file.resolver.getOrPut(gpa, .{
220 .index = @intCast(i),
221 .file = self.index,
222 }, macho_file);
223 if (!gop.found_existing) {
224 gop.ref.* = .{ .index = 0, .file = 0 };
225 }
226 global.* = gop.index;
227
228 if (nlist.undf() and !nlist.tentative()) continue;
229 if (gop.ref.getFile(macho_file) == null) {
230 gop.ref.* = .{ .index = @intCast(i), .file = self.index };
231 continue;
232 }
233
224234 if (self.asFile().getSymbolRank(.{
225235 .archive = false,
226236 .weak = nlist.weakDef(),
227237 .tentative = nlist.tentative(),
228 }) < symbol.getSymbolRank(macho_file)) {
229 const value = if (nlist.sect()) blk: {
230 const atom = macho_file.getAtom(atom_index).?;
231 break :blk nlist.n_value - atom.getInputAddress(macho_file);
232 } else nlist.n_value;
233 const out_n_sect = if (nlist.sect()) macho_file.getAtom(atom_index).?.out_n_sect else 0;
234 symbol.value = value;
235 symbol.atom = atom_index;
236 symbol.out_n_sect = out_n_sect;
237 symbol.nlist_idx = nlist_idx;
238 symbol.file = self.index;
239 symbol.flags.weak = nlist.weakDef();
240 symbol.flags.abs = nlist.abs();
241 symbol.flags.tentative = nlist.tentative();
242 symbol.flags.weak_ref = false;
243 symbol.flags.dyn_ref = nlist.n_desc & macho.REFERENCED_DYNAMICALLY != 0;
244 symbol.flags.no_dead_strip = symbol.flags.no_dead_strip or nlist.noDeadStrip();
245 // TODO: symbol.flags.interposable = macho_file.base.isDynLib() and macho_file.options.namespace == .flat and !nlist.pext();
246 symbol.flags.interposable = false;
247
248 if (nlist.sect() and
249 macho_file.sections.items(.header)[nlist.n_sect - 1].type() == macho.S_THREAD_LOCAL_VARIABLES)
250 {
251 symbol.flags.tlv = true;
252 }
238 }) < gop.ref.getSymbol(macho_file).?.getSymbolRank(macho_file)) {
239 gop.ref.* = .{ .index = @intCast(i), .file = self.index };
253240 }
254
255 // Regardless of who the winner is, we still merge symbol visibility here.
256 if (nlist.pext() or (nlist.weakDef() and nlist.weakRef())) {
257 if (symbol.visibility != .global) {
258 symbol.visibility = .hidden;
259 }
260 } else {
261 symbol.visibility = .global;
262 }
263 }
264}
265
266pub fn resetGlobals(self: *ZigObject, macho_file: *MachO) void {
267 for (self.symbols.items, 0..) |sym_index, nlist_idx| {
268 if (!self.symtab.items(.nlist)[nlist_idx].ext()) continue;
269 const sym = macho_file.getSymbol(sym_index);
270 const name = sym.name;
271 const global = sym.flags.global;
272 const weak_ref = sym.flags.weak_ref;
273 sym.* = .{};
274 sym.name = name;
275 sym.flags.global = global;
276 sym.flags.weak_ref = weak_ref;
277241 }
278242}
279243
......@@ -281,12 +245,13 @@ pub fn markLive(self: *ZigObject, macho_file: *MachO) void {
281245 const tracy = trace(@src());
282246 defer tracy.end();
283247
284 for (self.symbols.items, 0..) |index, nlist_idx| {
285 const nlist = self.symtab.items(.nlist)[nlist_idx];
248 for (0..self.symbols.items.len) |i| {
249 const nlist = self.symtab.items(.nlist)[i];
286250 if (!nlist.ext()) continue;
287251
288 const sym = macho_file.getSymbol(index);
289 const file = sym.getFile(macho_file) orelse continue;
252 const ref = self.getSymbolRef(@intCast(i), macho_file);
253 const file = ref.getFile(macho_file) orelse continue;
254 const sym = ref.getSymbol(macho_file).?;
290255 const should_keep = nlist.undf() or (nlist.tentative() and !sym.flags.tentative);
291256 if (should_keep and file == .object and !file.object.alive) {
292257 file.object.alive = true;
......@@ -295,24 +260,41 @@ pub fn markLive(self: *ZigObject, macho_file: *MachO) void {
295260 }
296261}
297262
298pub fn checkDuplicates(self: *ZigObject, dupes: anytype, macho_file: *MachO) !void {
299 for (self.symbols.items, 0..) |index, nlist_idx| {
300 const sym = macho_file.getSymbol(index);
301 if (sym.visibility != .global) continue;
302 const file = sym.getFile(macho_file) orelse continue;
303 if (file.getIndex() == self.index) continue;
304
305 const nlist = self.symtab.items(.nlist)[nlist_idx];
306 if (!nlist.undf() and !nlist.tentative() and !(nlist.weakDef() or nlist.pext())) {
307 const gop = try dupes.getOrPut(index);
308 if (!gop.found_existing) {
309 gop.value_ptr.* = .{};
310 }
311 try gop.value_ptr.append(macho_file.base.comp.gpa, self.index);
263pub fn mergeSymbolVisibility(self: *ZigObject, macho_file: *MachO) void {
264 const tracy = trace(@src());
265 defer tracy.end();
266
267 for (self.symbols.items, 0..) |sym, i| {
268 const ref = self.getSymbolRef(@intCast(i), macho_file);
269 const global = ref.getSymbol(macho_file) orelse continue;
270 if (global.visibility != .global) {
271 global.visibility = sym.visibility;
272 }
273 if (sym.flags.weak_ref) {
274 global.flags.weak_ref = true;
312275 }
313276 }
314277}
315278
279// TODO
280// pub fn checkDuplicates(self: *ZigObject, dupes: anytype, macho_file: *MachO) !void {
281// for (self.symbols.items, 0..) |index, nlist_idx| {
282// const sym = macho_file.getSymbol(index);
283// if (sym.visibility != .global) continue;
284// const file = sym.getFile(macho_file) orelse continue;
285// if (file.getIndex() == self.index) continue;
286
287// const nlist = self.symtab.items(.nlist)[nlist_idx];
288// if (!nlist.undf() and !nlist.tentative() and !(nlist.weakDef() or nlist.pext())) {
289// const gop = try dupes.getOrPut(index);
290// if (!gop.found_existing) {
291// gop.value_ptr.* = .{};
292// }
293// try gop.value_ptr.append(macho_file.base.comp.gpa, self.index);
294// }
295// }
296// }
297
316298pub fn resolveLiterals(self: *ZigObject, lp: *MachO.LiteralPool, macho_file: *MachO) !void {
317299 _ = self;
318300 _ = lp;
......@@ -362,8 +344,8 @@ pub fn writeAr(self: ZigObject, ar_format: Archive.Format, writer: anytype) !voi
362344}
363345
364346pub fn scanRelocs(self: *ZigObject, macho_file: *MachO) !void {
365 for (self.atoms.items) |atom_index| {
366 const atom = macho_file.getAtom(atom_index) orelse continue;
347 for (self.getAtoms()) |atom_index| {
348 const atom = self.getAtom(atom_index) orelse continue;
367349 if (!atom.flags.alive) continue;
368350 const sect = atom.getInputSection(macho_file);
369351 if (sect.isZerofill()) continue;
......@@ -371,46 +353,49 @@ pub fn scanRelocs(self: *ZigObject, macho_file: *MachO) !void {
371353 }
372354}
373355
374pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) !void {
356pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) void {
375357 const tracy = trace(@src());
376358 defer tracy.end();
377359
378 for (self.symbols.items) |sym_index| {
379 const sym = macho_file.getSymbol(sym_index);
380 const file = sym.getFile(macho_file) orelse continue;
360 for (self.symbols.items, 0..) |*sym, i| {
361 const ref = self.getSymbolRef(@intCast(i), macho_file);
362 const file = ref.getFile(macho_file) orelse continue;
381363 if (file.getIndex() != self.index) continue;
382364 if (sym.getAtom(macho_file)) |atom| if (!atom.flags.alive) continue;
383365 sym.flags.output_symtab = true;
384366 if (sym.isLocal()) {
385 try sym.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, macho_file);
367 sym.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, macho_file);
386368 self.output_symtab_ctx.nlocals += 1;
387369 } else if (sym.flags.@"export") {
388 try sym.addExtra(.{ .symtab = self.output_symtab_ctx.nexports }, macho_file);
370 sym.addExtra(.{ .symtab = self.output_symtab_ctx.nexports }, macho_file);
389371 self.output_symtab_ctx.nexports += 1;
390372 } else {
391373 assert(sym.flags.import);
392 try sym.addExtra(.{ .symtab = self.output_symtab_ctx.nimports }, macho_file);
374 sym.addExtra(.{ .symtab = self.output_symtab_ctx.nimports }, macho_file);
393375 self.output_symtab_ctx.nimports += 1;
394376 }
395377 self.output_symtab_ctx.strsize += @as(u32, @intCast(sym.getName(macho_file).len + 1));
396378 }
397379}
398380
399pub fn writeSymtab(self: ZigObject, macho_file: *MachO, ctx: anytype) void {
381pub fn writeSymtab(self: ZigObject, macho_file: *MachO) void {
400382 const tracy = trace(@src());
401383 defer tracy.end();
402384
403 for (self.symbols.items) |sym_index| {
404 const sym = macho_file.getSymbol(sym_index);
405 const file = sym.getFile(macho_file) orelse continue;
385 var n_strx = self.output_symtab_ctx.stroff;
386 for (self.symbols.items, 0..) |sym, i| {
387 const ref = self.getSymbolRef(@intCast(i), macho_file);
388 const file = ref.getFile(macho_file) orelse continue;
406389 if (file.getIndex() != self.index) continue;
407390 const idx = sym.getOutputSymtabIndex(macho_file) orelse continue;
408 const n_strx = @as(u32, @intCast(ctx.strtab.items.len));
409 ctx.strtab.appendSliceAssumeCapacity(sym.getName(macho_file));
410 ctx.strtab.appendAssumeCapacity(0);
411 const out_sym = &ctx.symtab.items[idx];
391 const out_sym = &macho_file.symtab.items[idx];
412392 out_sym.n_strx = n_strx;
413393 sym.setOutputSym(macho_file, out_sym);
394 const name = sym.getName(macho_file);
395 @memcpy(macho_file.strtab.items[n_strx..][0..name.len], name);
396 n_strx += @intCast(name.len);
397 macho_file.strtab.items[n_strx] = 0;
398 n_strx += 1;
414399 }
415400}
416401
......@@ -523,9 +508,9 @@ pub fn getDeclVAddr(
523508 reloc_info: link.File.RelocInfo,
524509) !u64 {
525510 const sym_index = try self.getOrCreateMetadataForDecl(macho_file, decl_index);
526 const sym = macho_file.getSymbol(sym_index);
511 const sym = self.symbols.items[sym_index];
527512 const vaddr = sym.getAddress(.{}, macho_file);
528 const parent_atom = macho_file.getSymbol(reloc_info.parent_atom_index).getAtom(macho_file).?;
513 const parent_atom = self.symbols.items[reloc_info.parent_atom_index].getAtom(macho_file).?;
529514 try parent_atom.addReloc(macho_file, .{
530515 .tag = .@"extern",
531516 .offset = @intCast(reloc_info.offset),
......@@ -549,9 +534,9 @@ pub fn getAnonDeclVAddr(
549534 reloc_info: link.File.RelocInfo,
550535) !u64 {
551536 const sym_index = self.anon_decls.get(decl_val).?.symbol_index;
552 const sym = macho_file.getSymbol(sym_index);
537 const sym = self.symbols.items[sym_index];
553538 const vaddr = sym.getAddress(.{}, macho_file);
554 const parent_atom = macho_file.getSymbol(reloc_info.parent_atom_index).getAtom(macho_file).?;
539 const parent_atom = self.symbols.items[reloc_info.parent_atom_index].getAtom(macho_file).?;
555540 try parent_atom.addReloc(macho_file, .{
556541 .tag = .@"extern",
557542 .offset = @intCast(reloc_info.offset),
......@@ -584,7 +569,7 @@ pub fn lowerAnonDecl(
584569 else => explicit_alignment,
585570 };
586571 if (self.anon_decls.get(decl_val)) |metadata| {
587 const existing_alignment = macho_file.getSymbol(metadata.symbol_index).getAtom(macho_file).?.alignment;
572 const existing_alignment = self.symbols.items[metadata.symbol_index].getAtom(macho_file).?.alignment;
588573 if (decl_alignment.order(existing_alignment).compare(.lte))
589574 return .ok;
590575 }
......@@ -628,13 +613,10 @@ fn freeUnnamedConsts(self: *ZigObject, macho_file: *MachO, decl_index: InternPoo
628613}
629614
630615fn freeDeclMetadata(self: *ZigObject, macho_file: *MachO, sym_index: Symbol.Index) void {
631 _ = self;
632 const gpa = macho_file.base.comp.gpa;
633 const sym = macho_file.getSymbol(sym_index);
616 const sym = self.symbols.items[sym_index];
634617 sym.getAtom(macho_file).?.free(macho_file);
635618 log.debug("adding %{d} to local symbols free list", .{sym_index});
636 macho_file.symbols_free_list.append(gpa, sym_index) catch {};
637 macho_file.symbols.items[sym_index] = .{};
619 // TODO redo this
638620 // TODO free GOT entry here
639621}
640622
......@@ -675,7 +657,7 @@ pub fn updateFunc(
675657
676658 const sym_index = try self.getOrCreateMetadataForDecl(macho_file, decl_index);
677659 self.freeUnnamedConsts(macho_file, decl_index);
678 macho_file.getSymbol(sym_index).getAtom(macho_file).?.freeRelocs(macho_file);
660 self.symbols.items[sym_index].getAtom(macho_file).?.freeRelocs(macho_file);
679661
680662 var code_buffer = std.ArrayList(u8).init(gpa);
681663 defer code_buffer.deinit();
......@@ -708,7 +690,7 @@ pub fn updateFunc(
708690 try self.updateDeclCode(macho_file, pt, decl_index, sym_index, sect_index, code);
709691
710692 if (decl_state) |*ds| {
711 const sym = macho_file.getSymbol(sym_index);
693 const sym = self.symbols.items[sym_index];
712694 try self.dwarf.?.commitDeclState(
713695 pt,
714696 decl_index,
......@@ -743,13 +725,13 @@ pub fn updateDecl(
743725 const name = decl.name.toSlice(&mod.intern_pool);
744726 const lib_name = variable.lib_name.toSlice(&mod.intern_pool);
745727 const index = try self.getGlobalSymbol(macho_file, name, lib_name);
746 const actual_index = self.symbols.items[index];
747 macho_file.getSymbol(actual_index).flags.needs_got = true;
728 const sym = &self.symbols.items[index];
729 sym.flags.needs_got = true;
748730 return;
749731 }
750732
751733 const sym_index = try self.getOrCreateMetadataForDecl(macho_file, decl_index);
752 macho_file.getSymbol(sym_index).getAtom(macho_file).?.freeRelocs(macho_file);
734 self.symbols.items[sym_index].getAtom(macho_file).?.freeRelocs(macho_file);
753735
754736 const gpa = macho_file.base.comp.gpa;
755737 var code_buffer = std.ArrayList(u8).init(gpa);
......@@ -784,7 +766,7 @@ pub fn updateDecl(
784766 }
785767
786768 if (decl_state) |*ds| {
787 const sym = macho_file.getSymbol(sym_index);
769 const sym = self.symbols.items[sym_index];
788770 try self.dwarf.?.commitDeclState(
789771 pt,
790772 decl_index,
......@@ -816,7 +798,7 @@ fn updateDeclCode(
816798 const required_alignment = decl.getAlignment(pt);
817799
818800 const sect = &macho_file.sections.items(.header)[sect_index];
819 const sym = macho_file.getSymbol(sym_index);
801 const sym = &self.symbols.items[sym_index];
820802 const nlist = &self.symtab.items(.nlist)[sym.nlist_idx];
821803 const atom = sym.getAtom(macho_file).?;
822804
......@@ -850,13 +832,13 @@ fn updateDeclCode(
850832 if (!macho_file.base.isRelocatable()) {
851833 log.debug(" (updating offset table entry)", .{});
852834 assert(sym.flags.has_zig_got);
853 const extra = sym.getExtra(macho_file).?;
835 const extra = sym.getExtra(macho_file);
854836 try macho_file.zig_got.writeOne(macho_file, extra.zig_got);
855837 }
856838 }
857839 } else if (code.len < old_size) {
858840 atom.shrink(macho_file);
859 } else if (macho_file.getAtom(atom.next_index) == null) {
841 } else if (self.getAtom(atom.next_index) == null) {
860842 const needed_size = atom.value + code.len;
861843 sect.size = needed_size;
862844 }
......@@ -922,8 +904,8 @@ fn createTlvInitializer(
922904 const sym_name = try std.fmt.allocPrint(gpa, "{s}$tlv$init", .{name});
923905 defer gpa.free(sym_name);
924906
925 const sym_index = try self.addAtom(macho_file);
926 const sym = macho_file.getSymbol(sym_index);
907 const sym_index = try self.createAtomForDecl(gpa, macho_file);
908 const sym = &self.symbols.items[sym_index];
927909 const nlist = &self.symtab.items(.nlist)[sym.nlist_idx];
928910 const atom = sym.getAtom(macho_file).?;
929911
......@@ -945,7 +927,6 @@ fn createTlvInitializer(
945927
946928 const slice = macho_file.sections.slice();
947929 const header = slice.items(.header)[sect_index];
948 const atoms = &slice.items(.atoms)[sect_index];
949930
950931 const gop = try self.tlv_initializers.getOrPut(gpa, atom.atom_index);
951932 assert(!gop.found_existing); // TODO incremental updates
......@@ -956,8 +937,6 @@ fn createTlvInitializer(
956937 gop.value_ptr.data = try gpa.dupe(u8, code);
957938 }
958939
959 try atoms.append(gpa, atom.atom_index);
960
961940 return sym_index;
962941}
963942
......@@ -970,7 +949,7 @@ fn createTlvDescriptor(
970949) !void {
971950 const gpa = macho_file.base.comp.gpa;
972951
973 const sym = macho_file.getSymbol(sym_index);
952 const sym = &self.symbols.items[sym_index];
974953 const nlist = &self.symtab.items(.nlist)[sym.nlist_idx];
975954 const atom = sym.getAtom(macho_file).?;
976955 const alignment = Atom.Alignment.fromNonzeroByteUnits(@alignOf(u64));
......@@ -1000,7 +979,7 @@ fn createTlvDescriptor(
1000979 try atom.addReloc(macho_file, .{
1001980 .tag = .@"extern",
1002981 .offset = 0,
1003 .target = self.symbols.items[tlv_bootstrap_index],
982 .target = tlv_bootstrap_index,
1004983 .addend = 0,
1005984 .type = .unsigned,
1006985 .meta = .{
......@@ -1020,11 +999,14 @@ fn createTlvDescriptor(
1020999 .pcrel = false,
10211000 .has_subtractor = false,
10221001 .length = 3,
1023 .symbolnum = @intCast(macho_file.getSymbol(init_sym_index).nlist_idx),
1002 .symbolnum = @intCast(init_sym_index),
10241003 },
10251004 });
10261005
1027 try macho_file.sections.items(.atoms)[sect_index].append(gpa, atom.atom_index);
1006 try macho_file.sections.items(.atoms)[sect_index].append(gpa, .{
1007 .index = atom.atom_index,
1008 .file = self.index,
1009 });
10281010}
10291011
10301012fn getDeclOutputSection(
......@@ -1115,7 +1097,7 @@ pub fn lowerUnnamedConst(
11151097 return error.CodegenFail;
11161098 },
11171099 };
1118 const sym = macho_file.getSymbol(sym_index);
1100 const sym = self.symbols.items[sym_index];
11191101 try unnamed_consts.append(gpa, sym.atom);
11201102 return sym_index;
11211103}
......@@ -1140,7 +1122,7 @@ fn lowerConst(
11401122 var code_buffer = std.ArrayList(u8).init(gpa);
11411123 defer code_buffer.deinit();
11421124
1143 const sym_index = try self.addAtom(macho_file);
1125 const sym_index = try self.createAtomForDecl(gpa, macho_file);
11441126
11451127 const res = try codegen.generateSymbol(&macho_file.base, pt, src_loc, val, &code_buffer, .{
11461128 .none = {},
......@@ -1152,7 +1134,7 @@ fn lowerConst(
11521134 .fail => |em| return .{ .fail = em },
11531135 };
11541136
1155 const sym = macho_file.getSymbol(sym_index);
1137 const sym = &self.symbols.items[sym_index];
11561138 const name_str_index = try self.strtab.insert(gpa, name);
11571139 sym.name = name_str_index;
11581140 sym.out_n_sect = output_section_index;
......@@ -1218,7 +1200,7 @@ pub fn updateExports(
12181200 },
12191201 };
12201202 const sym_index = metadata.symbol_index;
1221 const nlist_idx = macho_file.getSymbol(sym_index).nlist_idx;
1203 const nlist_idx = self.symbols.items[sym_index].nlist_idx;
12221204 const nlist = self.symtab.items(.nlist)[nlist_idx];
12231205
12241206 for (export_indices) |export_idx| {
......@@ -1322,7 +1304,7 @@ fn updateLazySymbol(
13221304 .code => macho_file.zig_text_sect_index.?,
13231305 .const_data => macho_file.zig_const_sect_index.?,
13241306 };
1325 const sym = macho_file.getSymbol(symbol_index);
1307 const sym = &self.symbols.items[symbol_index];
13261308 sym.name = name_str_index;
13271309 sym.out_n_sect = output_section_index;
13281310
......@@ -1382,12 +1364,12 @@ pub fn deleteExport(
13821364 const nlist = &self.symtab.items(.nlist)[nlist_index.*];
13831365 self.symtab.items(.size)[nlist_index.*] = 0;
13841366 _ = self.globals_lookup.remove(nlist.n_strx);
1385 const sym_index = macho_file.globals.get(nlist.n_strx).?;
1386 const sym = macho_file.getSymbol(sym_index);
1387 if (sym.file == self.index) {
1388 _ = macho_file.globals.swapRemove(nlist.n_strx);
1389 sym.* = .{};
1390 }
1367 // TODO actually remove the export
1368 // const sym_index = macho_file.globals.get(nlist.n_strx).?;
1369 // const sym = &self.symbols.items[sym_index];
1370 // if (sym.file == self.index) {
1371 // sym.* = .{};
1372 // }
13911373 nlist.* = MachO.null_sym;
13921374}
13931375
......@@ -1404,9 +1386,11 @@ pub fn getGlobalSymbol(self: *ZigObject, macho_file: *MachO, name: []const u8, l
14041386 nlist.n_strx = off;
14051387 nlist.n_type = macho.N_EXT;
14061388 lookup_gop.value_ptr.* = nlist_index;
1407 const global_name_off = try macho_file.strings.insert(gpa, sym_name);
1408 const gop = try macho_file.getOrCreateGlobal(global_name_off);
1409 try self.symbols.append(gpa, gop.index);
1389 _ = try macho_file.resolver.getOrPut(gpa, .{
1390 .index = nlist_index,
1391 .file = self.index,
1392 }, macho_file);
1393 try self.globals.append(gpa, nlist_index);
14101394 }
14111395 return lookup_gop.value_ptr.*;
14121396}
......@@ -1420,10 +1404,10 @@ pub fn getOrCreateMetadataForDecl(
14201404 const gop = try self.decls.getOrPut(gpa, decl_index);
14211405 if (!gop.found_existing) {
14221406 const any_non_single_threaded = macho_file.base.comp.config.any_non_single_threaded;
1423 const sym_index = try self.addAtom(macho_file);
1407 const sym_index = try self.createAtomForDecl(gpa, macho_file);
14241408 const mod = macho_file.base.comp.module.?;
14251409 const decl = mod.declPtr(decl_index);
1426 const sym = macho_file.getSymbol(sym_index);
1410 const sym = &self.symbols.items[sym_index];
14271411 if (decl.getOwnedVariable(mod)) |variable| {
14281412 if (variable.is_threadlocal and any_non_single_threaded) {
14291413 sym.flags.tlv = true;
......@@ -1463,8 +1447,8 @@ pub fn getOrCreateMetadataForLazySymbol(
14631447 };
14641448 switch (metadata.state.*) {
14651449 .unused => {
1466 const symbol_index = try self.addAtom(macho_file);
1467 const sym = macho_file.getSymbol(symbol_index);
1450 const symbol_index = try self.createAtomForDecl(gpa, macho_file);
1451 const sym = &self.symbols.items[symbol_index];
14681452 sym.flags.needs_zig_got = true;
14691453 metadata.symbol_index.* = symbol_index;
14701454 },
......@@ -1478,6 +1462,130 @@ pub fn getOrCreateMetadataForLazySymbol(
14781462 return symbol_index;
14791463}
14801464
1465fn addAtom(self: *ZigObject, allocator: Allocator) !Atom.Index {
1466 const atom_index: Atom.Index = @intCast(self.atoms.items.len);
1467 const atom = try self.atoms.addOne(allocator);
1468 atom.* = .{
1469 .file = self.index,
1470 .atom_index = atom_index,
1471 .extra = try self.addAtomExtra(allocator, .{}),
1472 };
1473 return atom_index;
1474}
1475
1476pub fn getAtom(self: *ZigObject, atom_index: Atom.Index) ?*Atom {
1477 if (atom_index == 0) return null;
1478 assert(atom_index < self.atoms.items.len);
1479 return &self.atoms.items[atom_index];
1480}
1481
1482pub fn getAtoms(self: *ZigObject) []const Atom.Index {
1483 return self.atoms_indexes.items;
1484}
1485
1486fn addAtomExtra(self: *ZigObject, allocator: Allocator, extra: Atom.Extra) !u32 {
1487 const fields = @typeInfo(Atom.Extra).Struct.fields;
1488 try self.atoms_extra.ensureUnusedCapacity(allocator, fields.len);
1489 return self.addAtomExtraAssumeCapacity(extra);
1490}
1491
1492fn addAtomExtraAssumeCapacity(self: *ZigObject, extra: Atom.Extra) u32 {
1493 const index = @as(u32, @intCast(self.atoms_extra.items.len));
1494 const fields = @typeInfo(Atom.Extra).Struct.fields;
1495 inline for (fields) |field| {
1496 self.atoms_extra.appendAssumeCapacity(switch (field.type) {
1497 u32 => @field(extra, field.name),
1498 else => @compileError("bad field type"),
1499 });
1500 }
1501 return index;
1502}
1503
1504pub fn getAtomExtra(self: ZigObject, index: u32) Atom.Extra {
1505 const fields = @typeInfo(Atom.Extra).Struct.fields;
1506 var i: usize = index;
1507 var result: Atom.Extra = undefined;
1508 inline for (fields) |field| {
1509 @field(result, field.name) = switch (field.type) {
1510 u32 => self.atoms_extra.items[i],
1511 else => @compileError("bad field type"),
1512 };
1513 i += 1;
1514 }
1515 return result;
1516}
1517
1518pub fn setAtomExtra(self: *ZigObject, index: u32, extra: Atom.Extra) void {
1519 assert(index > 0);
1520 const fields = @typeInfo(Atom.Extra).Struct.fields;
1521 inline for (fields, 0..) |field, i| {
1522 self.atoms_extra.items[index + i] = switch (field.type) {
1523 u32 => @field(extra, field.name),
1524 else => @compileError("bad field type"),
1525 };
1526 }
1527}
1528
1529fn addSymbol(self: *ZigObject, allocator: Allocator) !Symbol.Index {
1530 try self.symbols.ensureUnusedCapacity(allocator, 1);
1531 return self.addSymbolAssumeCapacity();
1532}
1533
1534fn addSymbolAssumeCapacity(self: *ZigObject) Symbol.Index {
1535 const index: Symbol.Index = @intCast(self.symbols.items.len);
1536 const symbol = self.symbols.addOneAssumeCapacity();
1537 symbol.* = .{ .file = self.index };
1538 return index;
1539}
1540
1541pub fn getSymbolRef(self: ZigObject, index: Symbol.Index, macho_file: *MachO) MachO.Ref {
1542 const global_index = self.globals.items[index];
1543 if (macho_file.resolver.get(global_index)) |ref| return ref;
1544 return .{ .index = index, .file = self.index };
1545}
1546
1547pub fn addSymbolExtra(self: *ZigObject, allocator: Allocator, extra: Symbol.Extra) !u32 {
1548 const fields = @typeInfo(Symbol.Extra).Struct.fields;
1549 try self.symbols_extra.ensureUnusedCapacity(allocator, fields.len);
1550 return self.addSymbolExtraAssumeCapacity(extra);
1551}
1552
1553fn addSymbolExtraAssumeCapacity(self: *ZigObject, extra: Symbol.Extra) u32 {
1554 const index = @as(u32, @intCast(self.symbols_extra.items.len));
1555 const fields = @typeInfo(Symbol.Extra).Struct.fields;
1556 inline for (fields) |field| {
1557 self.symbols_extra.appendAssumeCapacity(switch (field.type) {
1558 u32 => @field(extra, field.name),
1559 else => @compileError("bad field type"),
1560 });
1561 }
1562 return index;
1563}
1564
1565pub fn getSymbolExtra(self: ZigObject, index: u32) Symbol.Extra {
1566 const fields = @typeInfo(Symbol.Extra).Struct.fields;
1567 var i: usize = index;
1568 var result: Symbol.Extra = undefined;
1569 inline for (fields) |field| {
1570 @field(result, field.name) = switch (field.type) {
1571 u32 => self.symbols_extra.items[i],
1572 else => @compileError("bad field type"),
1573 };
1574 i += 1;
1575 }
1576 return result;
1577}
1578
1579pub fn setSymbolExtra(self: *ZigObject, index: u32, extra: Symbol.Extra) void {
1580 const fields = @typeInfo(Symbol.Extra).Struct.fields;
1581 inline for (fields, 0..) |field, i| {
1582 self.symbols_extra.items[index + i] = switch (field.type) {
1583 u32 => @field(extra, field.name),
1584 else => @compileError("bad field type"),
1585 };
1586 }
1587}
1588
14811589pub fn asFile(self: *ZigObject) File {
14821590 return .{ .zig_object = self };
14831591}
......@@ -1503,9 +1611,16 @@ fn formatSymtab(
15031611 _ = unused_fmt_string;
15041612 _ = options;
15051613 try writer.writeAll(" symbols\n");
1506 for (ctx.self.symbols.items) |index| {
1507 const sym = ctx.macho_file.getSymbol(index);
1508 try writer.print(" {}\n", .{sym.fmt(ctx.macho_file)});
1614 const self = ctx.self;
1615 const macho_file = ctx.macho_file;
1616 for (self.symbols.items, 0) |sym, i| {
1617 const ref = self.getSymbolRef(@intCast(i), macho_file);
1618 if (ref.getFile(macho_file) == null) {
1619 // TODO any better way of handling this?
1620 try writer.print(" {s} : unclaimed\n", .{sym.getName(macho_file)});
1621 } else {
1622 try writer.print(" {}\n", .{ref.getSymbol(macho_file).?.fmt(macho_file)});
1623 }
15091624 }
15101625}
15111626
......@@ -1524,10 +1639,12 @@ fn formatAtoms(
15241639) !void {
15251640 _ = unused_fmt_string;
15261641 _ = options;
1642 const self = ctx.self;
1643 const macho_file = ctx.macho_file;
15271644 try writer.writeAll(" atoms\n");
1528 for (ctx.self.atoms.items) |atom_index| {
1529 const atom = ctx.macho_file.getAtom(atom_index) orelse continue;
1530 try writer.print(" {}\n", .{atom.fmt(ctx.macho_file)});
1645 for (self.getAtoms()) |atom_index| {
1646 const atom = self.getAtom(atom_index) orelse continue;
1647 try writer.print(" {}\n", .{atom.fmt(macho_file)});
15311648 }
15321649}
15331650