Commit 2169a5559d
Changed files (3)
src
link
src/link/MachO/Atom.zig
@@ -324,6 +324,70 @@ pub fn grow(self: *Atom, macho_file: *MachO) !void {
try self.allocate(macho_file);
}
+pub fn free(self: *Atom, macho_file: *MachO) void {
+ log.debug("freeAtom {d} ({s})", .{ self.atom_index, self.getName(macho_file) });
+
+ const comp = macho_file.base.comp;
+ const gpa = comp.gpa;
+ const free_list = &macho_file.sections.items(.free_list)[self.out_n_sect];
+ const last_atom_index = &macho_file.sections.items(.last_atom_index)[self.out_n_sect];
+ var already_have_free_list_node = false;
+ {
+ var i: usize = 0;
+ // TODO turn free_list into a hash map
+ while (i < free_list.items.len) {
+ if (free_list.items[i] == self.atom_index) {
+ _ = free_list.swapRemove(i);
+ continue;
+ }
+ if (free_list.items[i] == self.prev_index) {
+ already_have_free_list_node = true;
+ }
+ i += 1;
+ }
+ }
+
+ if (macho_file.getAtom(last_atom_index.*)) |last_atom| {
+ if (last_atom.atom_index == self.atom_index) {
+ if (macho_file.getAtom(self.prev_index)) |_| {
+ // TODO shrink the section size here
+ last_atom_index.* = self.prev_index;
+ } else {
+ last_atom_index.* = 0;
+ }
+ }
+ }
+
+ if (macho_file.getAtom(self.prev_index)) |prev| {
+ prev.next_index = self.next_index;
+ if (!already_have_free_list_node and prev.*.freeListEligible(macho_file)) {
+ // The free list is heuristics, it doesn't have to be perfect, so we can
+ // ignore the OOM here.
+ free_list.append(gpa, prev.atom_index) catch {};
+ }
+ } else {
+ self.prev_index = 0;
+ }
+
+ if (macho_file.getAtom(self.next_index)) |next| {
+ next.prev_index = self.prev_index;
+ } else {
+ self.next_index = 0;
+ }
+
+ // TODO create relocs free list
+ self.freeRelocs(macho_file);
+ // TODO figure out how to free input section mappind in ZigModule
+ // const zig_object = macho_file.zigObjectPtr().?
+ // assert(zig_object.atoms.swapRemove(self.atom_index));
+ self.* = .{};
+}
+
+pub fn freeRelocs(self: *Atom, macho_file: *MachO) void {
+ self.getFile(macho_file).zig_object.freeAtomRelocs(self.*);
+ self.relocs.len = 0;
+}
+
pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {
const tracy = trace(@src());
defer tracy.end();
src/link/MachO/ZigObject.zig
@@ -129,6 +129,10 @@ pub fn getAtomRelocs(self: *ZigObject, atom: Atom) []const Relocation {
return relocs.items[0..atom.relocs.len];
}
+pub fn freeAtomRelocs(self: *ZigObject, atom: Atom) void {
+ self.relocs.items[atom.relocs.pos].clearRetainingCapacity();
+}
+
pub fn resolveSymbols(self: *ZigObject, macho_file: *MachO) void {
_ = self;
_ = macho_file;
@@ -263,11 +267,42 @@ pub fn lowerAnonDecl(
@panic("TODO lowerAnonDecl");
}
-pub fn freeDecl(self: *ZigObject, macho_file: *MachO, decl_index: InternPool.DeclIndex) void {
+fn freeUnnamedConsts(self: *ZigObject, macho_file: *MachO, decl_index: InternPool.DeclIndex) void {
+ const gpa = macho_file.base.comp.gpa;
+ const unnamed_consts = self.unnamed_consts.getPtr(decl_index) orelse return;
+ for (unnamed_consts.items) |sym_index| {
+ self.freeDeclMetadata(macho_file, sym_index);
+ }
+ unnamed_consts.clearAndFree(gpa);
+}
+
+fn freeDeclMetadata(self: *ZigObject, macho_file: *MachO, sym_index: Symbol.Index) void {
_ = self;
- _ = macho_file;
- _ = decl_index;
- @panic("TODO freeDecl");
+ const gpa = macho_file.base.comp.gpa;
+ const sym = macho_file.getSymbol(sym_index);
+ sym.getAtom(macho_file).?.free(macho_file);
+ log.debug("adding %{d} to local symbols free list", .{sym_index});
+ macho_file.symbols_free_list.append(gpa, sym_index) catch {};
+ macho_file.symbols.items[sym_index] = .{};
+ // TODO free GOT entry here
+}
+
+pub fn freeDecl(self: *ZigObject, macho_file: *MachO, decl_index: InternPool.DeclIndex) void {
+ const gpa = macho_file.base.comp.gpa;
+ const mod = macho_file.base.comp.module.?;
+ const decl = mod.declPtr(decl_index);
+
+ log.debug("freeDecl {*}", .{decl});
+
+ if (self.decls.fetchRemove(decl_index)) |const_kv| {
+ var kv = const_kv;
+ const sym_index = kv.value.symbol_index;
+ self.freeDeclMetadata(macho_file, sym_index);
+ self.freeUnnamedConsts(macho_file, decl_index);
+ kv.value.exports.deinit(gpa);
+ }
+
+ // TODO free decl in dSYM
}
pub fn updateFunc(
@@ -278,13 +313,61 @@ pub fn updateFunc(
air: Air,
liveness: Liveness,
) !void {
- _ = self;
- _ = macho_file;
- _ = mod;
- _ = func_index;
- _ = air;
- _ = liveness;
- @panic("TODO updateFunc");
+ const tracy = trace(@src());
+ defer tracy.end();
+
+ const gpa = macho_file.base.comp.gpa;
+ const func = mod.funcInfo(func_index);
+ const decl_index = func.owner_decl;
+ const decl = mod.declPtr(decl_index);
+
+ const sym_index = try self.getOrCreateMetadataForDecl(macho_file, decl_index);
+ self.freeUnnamedConsts(macho_file, decl_index);
+ macho_file.getSymbol(sym_index).getAtom(macho_file).?.freeRelocs(macho_file);
+
+ var code_buffer = std.ArrayList(u8).init(gpa);
+ defer code_buffer.deinit();
+
+ var decl_state: ?Dwarf.DeclState = null; // TODO: Dwarf
+ defer if (decl_state) |*ds| ds.deinit();
+
+ const dio: codegen.DebugInfoOutput = if (decl_state) |*ds| .{ .dwarf = ds } else .none;
+ const res = try codegen.generateFunction(
+ &macho_file.base,
+ decl.srcLoc(mod),
+ func_index,
+ air,
+ liveness,
+ &code_buffer,
+ dio,
+ );
+
+ const code = switch (res) {
+ .ok => code_buffer.items,
+ .fail => |em| {
+ decl.analysis = .codegen_failure;
+ try mod.failed_decls.put(mod.gpa, decl_index, em);
+ return;
+ },
+ };
+
+ const sect_index = try self.getDeclOutputSection(macho_file, decl, code);
+ try self.updateDeclCode(macho_file, decl_index, sym_index, sect_index, code);
+
+ // if (decl_state) |*ds| {
+ // const sym = elf_file.symbol(sym_index);
+ // try self.dwarf.?.commitDeclState(
+ // mod,
+ // decl_index,
+ // sym.value,
+ // sym.atom(elf_file).?.size,
+ // ds,
+ // );
+ // }
+
+ // Since we updated the vaddr and the size, each corresponding export
+ // symbol also needs to be updated.
+ return self.updateExports(macho_file, mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index));
}
pub fn updateDecl(
@@ -313,7 +396,7 @@ pub fn updateDecl(
}
const sym_index = try self.getOrCreateMetadataForDecl(macho_file, decl_index);
- // TODO: free relocs if any
+ macho_file.getSymbol(sym_index).getAtom(macho_file).?.freeRelocs(macho_file);
const gpa = macho_file.base.comp.gpa;
var code_buffer = std.ArrayList(u8).init(gpa);
@@ -431,7 +514,7 @@ fn updateDeclCode(
}
} else {
try atom.allocate(macho_file);
- // TODO: freeDeclMetadata in case of error
+ errdefer self.freeDeclMetadata(macho_file, sym_index);
sym.value = 0;
sym.flags.needs_zig_got = true;
src/link/MachO.zig
@@ -20,6 +20,7 @@ sections: std.MultiArrayList(Section) = .{},
symbols: std.ArrayListUnmanaged(Symbol) = .{},
symbols_extra: std.ArrayListUnmanaged(u32) = .{},
+symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{},
globals: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{},
/// This table will be populated after `scanRelocs` has run.
/// Key is symbol index.
@@ -327,6 +328,7 @@ pub fn deinit(self: *MachO) void {
self.symbols.deinit(gpa);
self.symbols_extra.deinit(gpa);
+ self.symbols_free_list.deinit(gpa);
self.globals.deinit(gpa);
{
var it = self.undefs.iterator();
@@ -3260,9 +3262,8 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
}
pub fn growSection(self: *MachO, sect_index: u8, size: u64) !void {
- _ = self;
- _ = sect_index;
- _ = size;
+ const sect = &self.sections.items(.header)[sect_index];
+ std.debug.print("curr={x}, needed={x}\n", .{ sect.size, size });
@panic("TODO growSection");
}