authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-18 14:59:15+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-24 12:34:41+01:00
log2169a5559dedd1ea245264a0e642347677af91b8
tree605e0b6aed26bc45c4affae60f2407500532b509
parent55c8b82b50a6b1f2d65775f8d2ad313833549067

macho: implement more self-hosted primitives


3 files changed, 164 insertions(+), 16 deletions(-)

src/link/MachO.zig+4-3
...@@ -20,6 +20,7 @@ sections: std.MultiArrayList(Section) = .{},...@@ -20,6 +20,7 @@ sections: std.MultiArrayList(Section) = .{},
2020
21symbols: std.ArrayListUnmanaged(Symbol) = .{},21symbols: std.ArrayListUnmanaged(Symbol) = .{},
22symbols_extra: std.ArrayListUnmanaged(u32) = .{},22symbols_extra: std.ArrayListUnmanaged(u32) = .{},
23symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{},
23globals: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{},24globals: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{},
24/// This table will be populated after `scanRelocs` has run.25/// This table will be populated after `scanRelocs` has run.
25/// Key is symbol index.26/// Key is symbol index.
...@@ -327,6 +328,7 @@ pub fn deinit(self: *MachO) void {...@@ -327,6 +328,7 @@ pub fn deinit(self: *MachO) void {
327328
328 self.symbols.deinit(gpa);329 self.symbols.deinit(gpa);
329 self.symbols_extra.deinit(gpa);330 self.symbols_extra.deinit(gpa);
331 self.symbols_free_list.deinit(gpa);
330 self.globals.deinit(gpa);332 self.globals.deinit(gpa);
331 {333 {
332 var it = self.undefs.iterator();334 var it = self.undefs.iterator();
...@@ -3260,9 +3262,8 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {...@@ -3260,9 +3262,8 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
3260}3262}
32613263
3262pub fn growSection(self: *MachO, sect_index: u8, size: u64) !void {3264pub fn growSection(self: *MachO, sect_index: u8, size: u64) !void {
3263 _ = self;3265 const sect = &self.sections.items(.header)[sect_index];
3264 _ = sect_index;3266 std.debug.print("curr={x}, needed={x}\n", .{ sect.size, size });
3265 _ = size;
3266 @panic("TODO growSection");3267 @panic("TODO growSection");
3267}3268}
32683269
src/link/MachO/Atom.zig+64
...@@ -324,6 +324,70 @@ pub fn grow(self: *Atom, macho_file: *MachO) !void {...@@ -324,6 +324,70 @@ pub fn grow(self: *Atom, macho_file: *MachO) !void {
324 try self.allocate(macho_file);324 try self.allocate(macho_file);
325}325}
326326
327pub fn free(self: *Atom, macho_file: *MachO) void {
328 log.debug("freeAtom {d} ({s})", .{ self.atom_index, self.getName(macho_file) });
329
330 const comp = macho_file.base.comp;
331 const gpa = comp.gpa;
332 const free_list = &macho_file.sections.items(.free_list)[self.out_n_sect];
333 const last_atom_index = &macho_file.sections.items(.last_atom_index)[self.out_n_sect];
334 var already_have_free_list_node = false;
335 {
336 var i: usize = 0;
337 // TODO turn free_list into a hash map
338 while (i < free_list.items.len) {
339 if (free_list.items[i] == self.atom_index) {
340 _ = free_list.swapRemove(i);
341 continue;
342 }
343 if (free_list.items[i] == self.prev_index) {
344 already_have_free_list_node = true;
345 }
346 i += 1;
347 }
348 }
349
350 if (macho_file.getAtom(last_atom_index.*)) |last_atom| {
351 if (last_atom.atom_index == self.atom_index) {
352 if (macho_file.getAtom(self.prev_index)) |_| {
353 // TODO shrink the section size here
354 last_atom_index.* = self.prev_index;
355 } else {
356 last_atom_index.* = 0;
357 }
358 }
359 }
360
361 if (macho_file.getAtom(self.prev_index)) |prev| {
362 prev.next_index = self.next_index;
363 if (!already_have_free_list_node and prev.*.freeListEligible(macho_file)) {
364 // The free list is heuristics, it doesn't have to be perfect, so we can
365 // ignore the OOM here.
366 free_list.append(gpa, prev.atom_index) catch {};
367 }
368 } else {
369 self.prev_index = 0;
370 }
371
372 if (macho_file.getAtom(self.next_index)) |next| {
373 next.prev_index = self.prev_index;
374 } else {
375 self.next_index = 0;
376 }
377
378 // TODO create relocs free list
379 self.freeRelocs(macho_file);
380 // TODO figure out how to free input section mappind in ZigModule
381 // const zig_object = macho_file.zigObjectPtr().?
382 // assert(zig_object.atoms.swapRemove(self.atom_index));
383 self.* = .{};
384}
385
386pub fn freeRelocs(self: *Atom, macho_file: *MachO) void {
387 self.getFile(macho_file).zig_object.freeAtomRelocs(self.*);
388 self.relocs.len = 0;
389}
390
327pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {391pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {
328 const tracy = trace(@src());392 const tracy = trace(@src());
329 defer tracy.end();393 defer tracy.end();
src/link/MachO/ZigObject.zig+96-13
...@@ -129,6 +129,10 @@ pub fn getAtomRelocs(self: *ZigObject, atom: Atom) []const Relocation {...@@ -129,6 +129,10 @@ pub fn getAtomRelocs(self: *ZigObject, atom: Atom) []const Relocation {
129 return relocs.items[0..atom.relocs.len];129 return relocs.items[0..atom.relocs.len];
130}130}
131131
132pub fn freeAtomRelocs(self: *ZigObject, atom: Atom) void {
133 self.relocs.items[atom.relocs.pos].clearRetainingCapacity();
134}
135
132pub fn resolveSymbols(self: *ZigObject, macho_file: *MachO) void {136pub fn resolveSymbols(self: *ZigObject, macho_file: *MachO) void {
133 _ = self;137 _ = self;
134 _ = macho_file;138 _ = macho_file;
...@@ -263,11 +267,42 @@ pub fn lowerAnonDecl(...@@ -263,11 +267,42 @@ pub fn lowerAnonDecl(
263 @panic("TODO lowerAnonDecl");267 @panic("TODO lowerAnonDecl");
264}268}
265269
266pub fn freeDecl(self: *ZigObject, macho_file: *MachO, decl_index: InternPool.DeclIndex) void {270fn freeUnnamedConsts(self: *ZigObject, macho_file: *MachO, decl_index: InternPool.DeclIndex) void {
271 const gpa = macho_file.base.comp.gpa;
272 const unnamed_consts = self.unnamed_consts.getPtr(decl_index) orelse return;
273 for (unnamed_consts.items) |sym_index| {
274 self.freeDeclMetadata(macho_file, sym_index);
275 }
276 unnamed_consts.clearAndFree(gpa);
277}
278
279fn freeDeclMetadata(self: *ZigObject, macho_file: *MachO, sym_index: Symbol.Index) void {
267 _ = self;280 _ = self;
268 _ = macho_file;281 const gpa = macho_file.base.comp.gpa;
269 _ = decl_index;282 const sym = macho_file.getSymbol(sym_index);
270 @panic("TODO freeDecl");283 sym.getAtom(macho_file).?.free(macho_file);
284 log.debug("adding %{d} to local symbols free list", .{sym_index});
285 macho_file.symbols_free_list.append(gpa, sym_index) catch {};
286 macho_file.symbols.items[sym_index] = .{};
287 // TODO free GOT entry here
288}
289
290pub fn freeDecl(self: *ZigObject, macho_file: *MachO, decl_index: InternPool.DeclIndex) void {
291 const gpa = macho_file.base.comp.gpa;
292 const mod = macho_file.base.comp.module.?;
293 const decl = mod.declPtr(decl_index);
294
295 log.debug("freeDecl {*}", .{decl});
296
297 if (self.decls.fetchRemove(decl_index)) |const_kv| {
298 var kv = const_kv;
299 const sym_index = kv.value.symbol_index;
300 self.freeDeclMetadata(macho_file, sym_index);
301 self.freeUnnamedConsts(macho_file, decl_index);
302 kv.value.exports.deinit(gpa);
303 }
304
305 // TODO free decl in dSYM
271}306}
272307
273pub fn updateFunc(308pub fn updateFunc(
...@@ -278,13 +313,61 @@ pub fn updateFunc(...@@ -278,13 +313,61 @@ pub fn updateFunc(
278 air: Air,313 air: Air,
279 liveness: Liveness,314 liveness: Liveness,
280) !void {315) !void {
281 _ = self;316 const tracy = trace(@src());
282 _ = macho_file;317 defer tracy.end();
283 _ = mod;318
284 _ = func_index;319 const gpa = macho_file.base.comp.gpa;
285 _ = air;320 const func = mod.funcInfo(func_index);
286 _ = liveness;321 const decl_index = func.owner_decl;
287 @panic("TODO updateFunc");322 const decl = mod.declPtr(decl_index);
323
324 const sym_index = try self.getOrCreateMetadataForDecl(macho_file, decl_index);
325 self.freeUnnamedConsts(macho_file, decl_index);
326 macho_file.getSymbol(sym_index).getAtom(macho_file).?.freeRelocs(macho_file);
327
328 var code_buffer = std.ArrayList(u8).init(gpa);
329 defer code_buffer.deinit();
330
331 var decl_state: ?Dwarf.DeclState = null; // TODO: Dwarf
332 defer if (decl_state) |*ds| ds.deinit();
333
334 const dio: codegen.DebugInfoOutput = if (decl_state) |*ds| .{ .dwarf = ds } else .none;
335 const res = try codegen.generateFunction(
336 &macho_file.base,
337 decl.srcLoc(mod),
338 func_index,
339 air,
340 liveness,
341 &code_buffer,
342 dio,
343 );
344
345 const code = switch (res) {
346 .ok => code_buffer.items,
347 .fail => |em| {
348 decl.analysis = .codegen_failure;
349 try mod.failed_decls.put(mod.gpa, decl_index, em);
350 return;
351 },
352 };
353
354 const sect_index = try self.getDeclOutputSection(macho_file, decl, code);
355 try self.updateDeclCode(macho_file, decl_index, sym_index, sect_index, code);
356
357 // if (decl_state) |*ds| {
358 // const sym = elf_file.symbol(sym_index);
359 // try self.dwarf.?.commitDeclState(
360 // mod,
361 // decl_index,
362 // sym.value,
363 // sym.atom(elf_file).?.size,
364 // ds,
365 // );
366 // }
367
368 // Since we updated the vaddr and the size, each corresponding export
369 // symbol also needs to be updated.
370 return self.updateExports(macho_file, mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index));
288}371}
289372
290pub fn updateDecl(373pub fn updateDecl(
...@@ -313,7 +396,7 @@ pub fn updateDecl(...@@ -313,7 +396,7 @@ pub fn updateDecl(
313 }396 }
314397
315 const sym_index = try self.getOrCreateMetadataForDecl(macho_file, decl_index);398 const sym_index = try self.getOrCreateMetadataForDecl(macho_file, decl_index);
316 // TODO: free relocs if any399 macho_file.getSymbol(sym_index).getAtom(macho_file).?.freeRelocs(macho_file);
317400
318 const gpa = macho_file.base.comp.gpa;401 const gpa = macho_file.base.comp.gpa;
319 var code_buffer = std.ArrayList(u8).init(gpa);402 var code_buffer = std.ArrayList(u8).init(gpa);
...@@ -431,7 +514,7 @@ fn updateDeclCode(...@@ -431,7 +514,7 @@ fn updateDeclCode(
431 }514 }
432 } else {515 } else {
433 try atom.allocate(macho_file);516 try atom.allocate(macho_file);
434 // TODO: freeDeclMetadata in case of error517 errdefer self.freeDeclMetadata(macho_file, sym_index);
435518
436 sym.value = 0;519 sym.value = 0;
437 sym.flags.needs_zig_got = true;520 sym.flags.needs_zig_got = true;