diff --git a/src/link.zig b/src/link.zig index 450763ac18..001cc709e4 100644 --- a/src/link.zig +++ b/src/link.zig @@ -223,7 +223,9 @@ pub const Options = struct { pub fn move(self: *Options) Options { const copied_state = self.*; + self.frameworks = .{}; self.system_libs = .{}; + self.force_undefined_symbols = .{}; return copied_state; } }; @@ -624,7 +626,9 @@ pub const File = struct { base.releaseLock(); if (base.file) |f| f.close(); if (base.intermediary_basename) |sub_path| base.allocator.free(sub_path); + base.options.frameworks.deinit(base.allocator); base.options.system_libs.deinit(base.allocator); + base.options.force_undefined_symbols.deinit(base.allocator); switch (base.tag) { .coff => { if (build_options.only_c) unreachable; diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 232342dd7f..9c05114a1f 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -289,6 +289,7 @@ pub fn deinit(self: *Coff) void { self.unresolved.deinit(gpa); self.locals_free_list.deinit(gpa); + self.globals_free_list.deinit(gpa); self.strtab.deinit(gpa); self.got_entries.deinit(gpa); self.got_entries_free_list.deinit(gpa); @@ -1150,8 +1151,10 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8, } fn freeRelocationsForAtom(self: *Coff, atom: *Atom) void { - _ = self.relocs.remove(atom); - _ = self.base_relocs.remove(atom); + var removed_relocs = self.relocs.fetchRemove(atom); + if (removed_relocs) |*relocs| relocs.value.deinit(self.base.allocator); + var removed_base_relocs = self.base_relocs.fetchRemove(atom); + if (removed_base_relocs) |*base_relocs| base_relocs.value.deinit(self.base.allocator); } fn freeUnnamedConsts(self: *Coff, decl_index: Module.Decl.Index) void { @@ -1489,9 +1492,8 @@ pub fn getGlobalSymbol(self: *Coff, name: []const u8) !u32 { gop.value_ptr.* = sym_loc; const gpa = self.base.allocator; - const sym_name = try gpa.dupe(u8, name); const sym = self.getSymbolPtr(sym_loc); - try self.setSymbolName(sym, sym_name); + try self.setSymbolName(sym, name); sym.storage_class = .EXTERNAL; try self.unresolved.putNoClobber(gpa, global_index, true); diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 824d39216a..be770574b8 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -2576,10 +2576,14 @@ pub fn deleteExport(self: *MachO, exp: Export) void { } fn freeRelocationsForAtom(self: *MachO, atom: *Atom) void { - _ = self.relocs.remove(atom); - _ = self.rebases.remove(atom); - _ = self.bindings.remove(atom); - _ = self.lazy_bindings.remove(atom); + var removed_relocs = self.relocs.fetchRemove(atom); + if (removed_relocs) |*relocs| relocs.value.deinit(self.base.allocator); + var removed_rebases = self.rebases.fetchRemove(atom); + if (removed_rebases) |*rebases| rebases.value.deinit(self.base.allocator); + var removed_bindings = self.bindings.fetchRemove(atom); + if (removed_bindings) |*bindings| bindings.value.deinit(self.base.allocator); + var removed_lazy_bindings = self.lazy_bindings.fetchRemove(atom); + if (removed_lazy_bindings) |*lazy_bindings| lazy_bindings.value.deinit(self.base.allocator); } fn freeUnnamedConsts(self: *MachO, decl_index: Module.Decl.Index) void { diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index 2d221463c9..5423269bf0 100644 --- a/src/link/Plan9.zig +++ b/src/link/Plan9.zig @@ -201,7 +201,10 @@ fn putFn(self: *Plan9, decl_index: Module.Decl.Index, out: FnDeclOutput) !void { const decl = mod.declPtr(decl_index); const fn_map_res = try self.fn_decl_table.getOrPut(gpa, decl.getFileScope()); if (fn_map_res.found_existing) { - try fn_map_res.value_ptr.functions.put(gpa, decl_index, out); + if (try fn_map_res.value_ptr.functions.fetchPut(gpa, decl_index, out)) |old_entry| { + gpa.free(old_entry.value.code); + gpa.free(old_entry.value.lineinfo); + } } else { const file = decl.getFileScope(); const arena = self.path_arena.allocator(); @@ -408,9 +411,11 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index) return; }, }; - var duped_code = try self.base.allocator.dupe(u8, code); - errdefer self.base.allocator.free(duped_code); - try self.data_decl_table.put(self.base.allocator, decl_index, duped_code); + try self.data_decl_table.ensureUnusedCapacity(self.base.allocator, 1); + const duped_code = try self.base.allocator.dupe(u8, code); + if (self.data_decl_table.fetchPutAssumeCapacity(decl_index, duped_code)) |old_entry| { + self.base.allocator.free(old_entry.value); + } return self.updateFinish(decl); } /// called at the end of update{Decl,Func} @@ -743,14 +748,19 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void { if (is_fn) { var symidx_and_submap = self.fn_decl_table.get(decl.getFileScope()).?; var submap = symidx_and_submap.functions; - _ = submap.swapRemove(decl_index); + if (submap.fetchSwapRemove(decl_index)) |removed_entry| { + self.base.allocator.free(removed_entry.value.code); + self.base.allocator.free(removed_entry.value.lineinfo); + } if (submap.count() == 0) { self.syms.items[symidx_and_submap.sym_index] = aout.Sym.undefined_symbol; self.syms_index_free_list.append(self.base.allocator, symidx_and_submap.sym_index) catch {}; submap.deinit(self.base.allocator); } } else { - _ = self.data_decl_table.swapRemove(decl_index); + if (self.data_decl_table.fetchSwapRemove(decl_index)) |removed_entry| { + self.base.allocator.free(removed_entry.value); + } } if (decl.link.plan9.got_index) |i| { // TODO: if this catch {} is triggered, an assertion in flushModule will be triggered, because got_index_free_list will have the wrong length diff --git a/test/cases/plan9/hello_world_with_updates.1.zig b/test/cases/plan9/hello_world_with_updates.1.zig index 4111a8dc08..410045ab79 100644 --- a/test/cases/plan9/hello_world_with_updates.1.zig +++ b/test/cases/plan9/hello_world_with_updates.1.zig @@ -5,6 +5,7 @@ pub fn main() void { } // run +// target=x86_64-plan9 // // Hello World //