authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-01-24 17:55:10+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-01-26 14:29:14+01:00
log4d804c1b239e45a0a28f4caf1f9748dac44ddce2
treeb22466da22ef55cbd69f1792939ceb378dc1e654
parent48f9e491cb97de54c7e8d395170d8b4c8ea9a62b

macho: completely remove allocateDeclIndexes in favor of linker tracking


6 files changed, 115 insertions(+), 88 deletions(-)

src/Module.zig+1-1
...@@ -5324,7 +5324,7 @@ pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void {...@@ -5324,7 +5324,7 @@ pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void {
5324 // Until then, we did call `allocateDeclIndexes` on this anonymous Decl and so we5324 // Until then, we did call `allocateDeclIndexes` on this anonymous Decl and so we
5325 // must call `freeDecl` in the linker backend now.5325 // must call `freeDecl` in the linker backend now.
5326 switch (mod.comp.bin_file.tag) {5326 switch (mod.comp.bin_file.tag) {
5327 .c => {}, // this linker backend has already migrated to the new API5327 .macho, .c => {}, // this linker backend has already migrated to the new API
5328 else => if (decl.has_tv) {5328 else => if (decl.has_tv) {
5329 if (decl.ty.isFnOrHasRuntimeBits()) {5329 if (decl.ty.isFnOrHasRuntimeBits()) {
5330 mod.comp.bin_file.freeDecl(decl_index);5330 mod.comp.bin_file.freeDecl(decl_index);
src/arch/aarch64/CodeGen.zig+10-9
...@@ -3999,7 +3999,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -3999,7 +3999,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
3999 const mod = self.bin_file.options.module.?;3999 const mod = self.bin_file.options.module.?;
4000 const owner_decl = mod.declPtr(self.mod_fn.owner_decl);4000 const owner_decl = mod.declPtr(self.mod_fn.owner_decl);
4001 const atom_index = switch (self.bin_file.tag) {4001 const atom_index = switch (self.bin_file.tag) {
4002 .macho => owner_decl.link.macho.sym_index,4002 .macho => owner_decl.link.macho.getSymbolIndex().?,
4003 .coff => owner_decl.link.coff.sym_index,4003 .coff => owner_decl.link.coff.sym_index,
4004 else => unreachable, // unsupported target format4004 else => unreachable, // unsupported target format
4005 };4005 };
...@@ -4328,10 +4328,11 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4328,10 +4328,11 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4328 if (func_value.castTag(.function)) |func_payload| {4328 if (func_value.castTag(.function)) |func_payload| {
4329 const func = func_payload.data;4329 const func = func_payload.data;
4330 const fn_owner_decl = mod.declPtr(func.owner_decl);4330 const fn_owner_decl = mod.declPtr(func.owner_decl);
4331 try fn_owner_decl.link.macho.ensureInitialized(macho_file);
4331 try self.genSetReg(Type.initTag(.u64), .x30, .{4332 try self.genSetReg(Type.initTag(.u64), .x30, .{
4332 .linker_load = .{4333 .linker_load = .{
4333 .type = .got,4334 .type = .got,
4334 .sym_index = fn_owner_decl.link.macho.sym_index,4335 .sym_index = fn_owner_decl.link.macho.getSymbolIndex().?,
4335 },4336 },
4336 });4337 });
4337 // blr x304338 // blr x30
...@@ -4354,7 +4355,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4354,7 +4355,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4354 .tag = .call_extern,4355 .tag = .call_extern,
4355 .data = .{4356 .data = .{
4356 .relocation = .{4357 .relocation = .{
4357 .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.sym_index,4358 .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.getSymbolIndex().?,
4358 .sym_index = sym_index,4359 .sym_index = sym_index,
4359 },4360 },
4360 },4361 },
...@@ -5537,7 +5538,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -5537,7 +5538,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
5537 const mod = self.bin_file.options.module.?;5538 const mod = self.bin_file.options.module.?;
5538 const owner_decl = mod.declPtr(self.mod_fn.owner_decl);5539 const owner_decl = mod.declPtr(self.mod_fn.owner_decl);
5539 const atom_index = switch (self.bin_file.tag) {5540 const atom_index = switch (self.bin_file.tag) {
5540 .macho => owner_decl.link.macho.sym_index,5541 .macho => owner_decl.link.macho.getSymbolIndex().?,
5541 .coff => owner_decl.link.coff.sym_index,5542 .coff => owner_decl.link.coff.sym_index,
5542 else => unreachable, // unsupported target format5543 else => unreachable, // unsupported target format
5543 };5544 };
...@@ -5651,7 +5652,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -5651,7 +5652,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
5651 const mod = self.bin_file.options.module.?;5652 const mod = self.bin_file.options.module.?;
5652 const owner_decl = mod.declPtr(self.mod_fn.owner_decl);5653 const owner_decl = mod.declPtr(self.mod_fn.owner_decl);
5653 const atom_index = switch (self.bin_file.tag) {5654 const atom_index = switch (self.bin_file.tag) {
5654 .macho => owner_decl.link.macho.sym_index,5655 .macho => owner_decl.link.macho.getSymbolIndex().?,
5655 .coff => owner_decl.link.coff.sym_index,5656 .coff => owner_decl.link.coff.sym_index,
5656 else => unreachable, // unsupported target format5657 else => unreachable, // unsupported target format
5657 };5658 };
...@@ -5845,7 +5846,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -5845,7 +5846,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
5845 const mod = self.bin_file.options.module.?;5846 const mod = self.bin_file.options.module.?;
5846 const owner_decl = mod.declPtr(self.mod_fn.owner_decl);5847 const owner_decl = mod.declPtr(self.mod_fn.owner_decl);
5847 const atom_index = switch (self.bin_file.tag) {5848 const atom_index = switch (self.bin_file.tag) {
5848 .macho => owner_decl.link.macho.sym_index,5849 .macho => owner_decl.link.macho.getSymbolIndex().?,
5849 .coff => owner_decl.link.coff.sym_index,5850 .coff => owner_decl.link.coff.sym_index,
5850 else => unreachable, // unsupported target format5851 else => unreachable, // unsupported target format
5851 };5852 };
...@@ -6168,13 +6169,13 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne...@@ -6168,13 +6169,13 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
6168 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];6169 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
6169 const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes;6170 const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes;
6170 return MCValue{ .memory = got_addr };6171 return MCValue{ .memory = got_addr };
6171 } else if (self.bin_file.cast(link.File.MachO)) |_| {6172 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
6172 // Because MachO is PIE-always-on, we defer memory address resolution until6173 // Because MachO is PIE-always-on, we defer memory address resolution until
6173 // the linker has enough info to perform relocations.6174 // the linker has enough info to perform relocations.
6174 assert(decl.link.macho.sym_index != 0);6175 try decl.link.macho.ensureInitialized(macho_file);
6175 return MCValue{ .linker_load = .{6176 return MCValue{ .linker_load = .{
6176 .type = .got,6177 .type = .got,
6177 .sym_index = decl.link.macho.sym_index,6178 .sym_index = decl.link.macho.getSymbolIndex().?,
6178 } };6179 } };
6179 } else if (self.bin_file.cast(link.File.Coff)) |_| {6180 } else if (self.bin_file.cast(link.File.Coff)) |_| {
6180 // Because COFF is PIE-always-on, we defer memory address resolution until6181 // Because COFF is PIE-always-on, we defer memory address resolution until
src/arch/x86_64/CodeGen.zig+7-6
...@@ -2671,7 +2671,7 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue...@@ -2671,7 +2671,7 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue
2671 const mod = self.bin_file.options.module.?;2671 const mod = self.bin_file.options.module.?;
2672 const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl);2672 const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl);
2673 const atom_index = if (self.bin_file.tag == link.File.MachO.base_tag)2673 const atom_index = if (self.bin_file.tag == link.File.MachO.base_tag)
2674 fn_owner_decl.link.macho.sym_index2674 fn_owner_decl.link.macho.getSymbolIndex().?
2675 else2675 else
2676 fn_owner_decl.link.coff.sym_index;2676 fn_owner_decl.link.coff.sym_index;
2677 const flags: u2 = switch (load_struct.type) {2677 const flags: u2 = switch (load_struct.type) {
...@@ -4090,7 +4090,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4090,7 +4090,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4090 if (func_value.castTag(.function)) |func_payload| {4090 if (func_value.castTag(.function)) |func_payload| {
4091 const func = func_payload.data;4091 const func = func_payload.data;
4092 const fn_owner_decl = mod.declPtr(func.owner_decl);4092 const fn_owner_decl = mod.declPtr(func.owner_decl);
4093 const sym_index = fn_owner_decl.link.macho.sym_index;4093 try fn_owner_decl.link.macho.ensureInitialized(macho_file);
4094 const sym_index = fn_owner_decl.link.macho.getSymbolIndex().?;
4094 try self.genSetReg(Type.initTag(.usize), .rax, .{4095 try self.genSetReg(Type.initTag(.usize), .rax, .{
4095 .linker_load = .{4096 .linker_load = .{
4096 .type = .got,4097 .type = .got,
...@@ -4121,7 +4122,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4121,7 +4122,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4121 .ops = undefined,4122 .ops = undefined,
4122 .data = .{4123 .data = .{
4123 .relocation = .{4124 .relocation = .{
4124 .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.sym_index,4125 .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.getSymbolIndex().?,
4125 .sym_index = sym_index,4126 .sym_index = sym_index,
4126 },4127 },
4127 },4128 },
...@@ -6784,11 +6785,11 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne...@@ -6784,11 +6785,11 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
6784 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];6785 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
6785 const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes;6786 const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes;
6786 return MCValue{ .memory = got_addr };6787 return MCValue{ .memory = got_addr };
6787 } else if (self.bin_file.cast(link.File.MachO)) |_| {6788 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
6788 assert(decl.link.macho.sym_index != 0);6789 try decl.link.macho.ensureInitialized(macho_file);
6789 return MCValue{ .linker_load = .{6790 return MCValue{ .linker_load = .{
6790 .type = .got,6791 .type = .got,
6791 .sym_index = decl.link.macho.sym_index,6792 .sym_index = decl.link.macho.getSymbolIndex().?,
6792 } };6793 } };
6793 } else if (self.bin_file.cast(link.File.Coff)) |_| {6794 } else if (self.bin_file.cast(link.File.Coff)) |_| {
6794 assert(decl.link.coff.sym_index != 0);6795 assert(decl.link.coff.sym_index != 0);
src/link.zig+3-1
...@@ -617,7 +617,7 @@ pub const File = struct {...@@ -617,7 +617,7 @@ pub const File = struct {
617 switch (base.tag) {617 switch (base.tag) {
618 .coff => return @fieldParentPtr(Coff, "base", base).allocateDeclIndexes(decl_index),618 .coff => return @fieldParentPtr(Coff, "base", base).allocateDeclIndexes(decl_index),
619 .elf => return @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl_index),619 .elf => return @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl_index),
620 .macho => return @fieldParentPtr(MachO, "base", base).allocateDeclIndexes(decl_index),620 .macho => {}, // no-op
621 .wasm => return @fieldParentPtr(Wasm, "base", base).allocateDeclIndexes(decl_index),621 .wasm => return @fieldParentPtr(Wasm, "base", base).allocateDeclIndexes(decl_index),
622 .plan9 => return @fieldParentPtr(Plan9, "base", base).allocateDeclIndexes(decl_index),622 .plan9 => return @fieldParentPtr(Plan9, "base", base).allocateDeclIndexes(decl_index),
623 .c, .spirv, .nvptx => {},623 .c, .spirv, .nvptx => {},
...@@ -911,6 +911,8 @@ pub const File = struct {...@@ -911,6 +911,8 @@ pub const File = struct {
911 /// The linker is passed information about the containing atom, `parent_atom_index`, and offset within it's911 /// The linker is passed information about the containing atom, `parent_atom_index`, and offset within it's
912 /// memory buffer, `offset`, so that it can make a note of potential relocation sites, should the912 /// memory buffer, `offset`, so that it can make a note of potential relocation sites, should the
913 /// `Decl`'s address was not yet resolved, or the containing atom gets moved in virtual memory.913 /// `Decl`'s address was not yet resolved, or the containing atom gets moved in virtual memory.
914 /// May be called before or after updateFunc/updateDecl therefore it is up to the linker to allocate
915 /// the block/atom.
914 pub fn getDeclVAddr(base: *File, decl_index: Module.Decl.Index, reloc_info: RelocInfo) !u64 {916 pub fn getDeclVAddr(base: *File, decl_index: Module.Decl.Index, reloc_info: RelocInfo) !u64 {
915 if (build_options.only_c) unreachable;917 if (build_options.only_c) unreachable;
916 switch (base.tag) {918 switch (base.tag) {
src/link/MachO.zig+72-63
...@@ -1811,6 +1811,8 @@ pub fn deinit(self: *MachO) void {...@@ -1811,6 +1811,8 @@ pub fn deinit(self: *MachO) void {
1811fn freeAtom(self: *MachO, atom: *Atom) void {1811fn freeAtom(self: *MachO, atom: *Atom) void {
1812 log.debug("freeAtom {*}", .{atom});1812 log.debug("freeAtom {*}", .{atom});
18131813
1814 const gpa = self.base.allocator;
1815
1814 // Remove any relocs and base relocs associated with this Atom1816 // Remove any relocs and base relocs associated with this Atom
1815 self.freeRelocationsForAtom(atom);1817 self.freeRelocationsForAtom(atom);
18161818
...@@ -1850,7 +1852,7 @@ fn freeAtom(self: *MachO, atom: *Atom) void {...@@ -1850,7 +1852,7 @@ fn freeAtom(self: *MachO, atom: *Atom) void {
1850 if (!already_have_free_list_node and prev.freeListEligible(self)) {1852 if (!already_have_free_list_node and prev.freeListEligible(self)) {
1851 // The free list is heuristics, it doesn't have to be perfect, so we can ignore1853 // The free list is heuristics, it doesn't have to be perfect, so we can ignore
1852 // the OOM here.1854 // the OOM here.
1853 free_list.append(self.base.allocator, prev) catch {};1855 free_list.append(gpa, prev) catch {};
1854 }1856 }
1855 } else {1857 } else {
1856 atom.prev = null;1858 atom.prev = null;
...@@ -1862,6 +1864,33 @@ fn freeAtom(self: *MachO, atom: *Atom) void {...@@ -1862,6 +1864,33 @@ fn freeAtom(self: *MachO, atom: *Atom) void {
1862 atom.next = null;1864 atom.next = null;
1863 }1865 }
18641866
1867 // Appending to free lists is allowed to fail because the free lists are heuristics based anyway.
1868 const sym_index = atom.getSymbolIndex().?;
1869
1870 self.locals_free_list.append(gpa, sym_index) catch {};
1871
1872 // Try freeing GOT atom if this decl had one
1873 const got_target = SymbolWithLoc{ .sym_index = sym_index, .file = null };
1874 if (self.got_entries_table.get(got_target)) |got_index| {
1875 self.got_entries_free_list.append(gpa, @intCast(u32, got_index)) catch {};
1876 self.got_entries.items[got_index] = .{
1877 .target = .{ .sym_index = 0, .file = null },
1878 .sym_index = 0,
1879 };
1880 _ = self.got_entries_table.remove(got_target);
1881
1882 if (self.d_sym) |*d_sym| {
1883 d_sym.swapRemoveRelocs(sym_index);
1884 }
1885
1886 log.debug(" adding GOT index {d} to free list (target local@{d})", .{ got_index, sym_index });
1887 }
1888
1889 self.locals.items[sym_index].n_type = 0;
1890 _ = self.atom_by_index_table.remove(sym_index);
1891 log.debug(" adding local symbol index {d} to free list", .{sym_index});
1892 atom.sym_index = 0;
1893
1865 if (self.d_sym) |*d_sym| {1894 if (self.d_sym) |*d_sym| {
1866 d_sym.dwarf.freeAtom(&atom.dbg_info_atom);1895 d_sym.dwarf.freeAtom(&atom.dbg_info_atom);
1867 }1896 }
...@@ -1883,7 +1912,7 @@ fn growAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) !u64...@@ -1883,7 +1912,7 @@ fn growAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) !u64
1883 return self.allocateAtom(atom, new_atom_size, alignment);1912 return self.allocateAtom(atom, new_atom_size, alignment);
1884}1913}
18851914
1886fn allocateSymbol(self: *MachO) !u32 {1915pub fn allocateSymbol(self: *MachO) !u32 {
1887 try self.locals.ensureUnusedCapacity(self.base.allocator, 1);1916 try self.locals.ensureUnusedCapacity(self.base.allocator, 1);
18881917
1889 const index = blk: {1918 const index = blk: {
...@@ -1975,16 +2004,6 @@ pub fn allocateStubEntry(self: *MachO, target: SymbolWithLoc) !u32 {...@@ -1975,16 +2004,6 @@ pub fn allocateStubEntry(self: *MachO, target: SymbolWithLoc) !u32 {
1975 return index;2004 return index;
1976}2005}
19772006
1978pub fn allocateDeclIndexes(self: *MachO, decl_index: Module.Decl.Index) !void {
1979 if (self.llvm_object) |_| return;
1980 const decl = self.base.options.module.?.declPtr(decl_index);
1981 if (decl.link.macho.sym_index != 0) return;
1982
1983 decl.link.macho.sym_index = try self.allocateSymbol();
1984 try self.atom_by_index_table.putNoClobber(self.base.allocator, decl.link.macho.sym_index, &decl.link.macho);
1985 try self.decls.putNoClobber(self.base.allocator, decl_index, null);
1986}
1987
1988pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {2007pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
1989 if (build_options.skip_non_native and builtin.object_format != .macho) {2008 if (build_options.skip_non_native and builtin.object_format != .macho) {
1990 @panic("Attempted to compile for object format that was disabled by build configuration");2009 @panic("Attempted to compile for object format that was disabled by build configuration");
...@@ -1997,8 +2016,15 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv...@@ -1997,8 +2016,15 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
19972016
1998 const decl_index = func.owner_decl;2017 const decl_index = func.owner_decl;
1999 const decl = module.declPtr(decl_index);2018 const decl = module.declPtr(decl_index);
2000 self.freeUnnamedConsts(decl_index);2019 const atom = &decl.link.macho;
2001 self.freeRelocationsForAtom(&decl.link.macho);2020 try atom.ensureInitialized(self);
2021 const gop = try self.decls.getOrPut(self.base.allocator, decl_index);
2022 if (gop.found_existing) {
2023 self.freeUnnamedConsts(decl_index);
2024 self.freeRelocationsForAtom(atom);
2025 } else {
2026 gop.value_ptr.* = null;
2027 }
20022028
2003 var code_buffer = std.ArrayList(u8).init(self.base.allocator);2029 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
2004 defer code_buffer.deinit();2030 defer code_buffer.deinit();
...@@ -2136,7 +2162,14 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)...@@ -2136,7 +2162,14 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)
2136 }2162 }
2137 }2163 }
21382164
2139 self.freeRelocationsForAtom(&decl.link.macho);2165 const atom = &decl.link.macho;
2166 try atom.ensureInitialized(self);
2167 const gop = try self.decls.getOrPut(self.base.allocator, decl_index);
2168 if (gop.found_existing) {
2169 self.freeRelocationsForAtom(atom);
2170 } else {
2171 gop.value_ptr.* = null;
2172 }
21402173
2141 var code_buffer = std.ArrayList(u8).init(self.base.allocator);2174 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
2142 defer code_buffer.deinit();2175 defer code_buffer.deinit();
...@@ -2337,12 +2370,12 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []const u8)...@@ -2337,12 +2370,12 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []const u8)
2337 const decl = mod.declPtr(decl_index);2370 const decl = mod.declPtr(decl_index);
23382371
2339 const required_alignment = decl.getAlignment(self.base.options.target);2372 const required_alignment = decl.getAlignment(self.base.options.target);
2340 assert(decl.link.macho.sym_index != 0); // Caller forgot to call allocateDeclIndexes()
23412373
2342 const sym_name = try decl.getFullyQualifiedName(mod);2374 const sym_name = try decl.getFullyQualifiedName(mod);
2343 defer self.base.allocator.free(sym_name);2375 defer self.base.allocator.free(sym_name);
23442376
2345 const atom = &decl.link.macho;2377 const atom = &decl.link.macho;
2378 const sym_index = atom.getSymbolIndex().?; // Atom was not initialized
2346 const decl_ptr = self.decls.getPtr(decl_index).?;2379 const decl_ptr = self.decls.getPtr(decl_index).?;
2347 if (decl_ptr.* == null) {2380 if (decl_ptr.* == null) {
2348 decl_ptr.* = self.getDeclOutputSection(decl);2381 decl_ptr.* = self.getDeclOutputSection(decl);
...@@ -2368,7 +2401,7 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []const u8)...@@ -2368,7 +2401,7 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []const u8)
2368 if (vaddr != sym.n_value) {2401 if (vaddr != sym.n_value) {
2369 sym.n_value = vaddr;2402 sym.n_value = vaddr;
2370 log.debug(" (updating GOT entry)", .{});2403 log.debug(" (updating GOT entry)", .{});
2371 const got_target = SymbolWithLoc{ .sym_index = atom.sym_index, .file = null };2404 const got_target = SymbolWithLoc{ .sym_index = sym_index, .file = null };
2372 const got_atom = self.getGotAtomForSymbol(got_target).?;2405 const got_atom = self.getGotAtomForSymbol(got_target).?;
2373 self.markRelocsDirtyByTarget(got_target);2406 self.markRelocsDirtyByTarget(got_target);
2374 try self.writePtrWidthAtom(got_atom);2407 try self.writePtrWidthAtom(got_atom);
...@@ -2399,10 +2432,10 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []const u8)...@@ -2399,10 +2432,10 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []const u8)
2399 atom.size = code_len;2432 atom.size = code_len;
2400 sym.n_value = vaddr;2433 sym.n_value = vaddr;
24012434
2402 const got_target = SymbolWithLoc{ .sym_index = atom.sym_index, .file = null };2435 const got_target = SymbolWithLoc{ .sym_index = sym_index, .file = null };
2403 const got_index = try self.allocateGotEntry(got_target);2436 const got_index = try self.allocateGotEntry(got_target);
2404 const got_atom = try self.createGotAtom(got_target);2437 const got_atom = try self.createGotAtom(got_target);
2405 self.got_entries.items[got_index].sym_index = got_atom.sym_index;2438 self.got_entries.items[got_index].sym_index = got_atom.getSymbolIndex().?;
2406 try self.writePtrWidthAtom(got_atom);2439 try self.writePtrWidthAtom(got_atom);
2407 }2440 }
24082441
...@@ -2438,7 +2471,14 @@ pub fn updateDeclExports(...@@ -2438,7 +2471,14 @@ pub fn updateDeclExports(
2438 const gpa = self.base.allocator;2471 const gpa = self.base.allocator;
24392472
2440 const decl = module.declPtr(decl_index);2473 const decl = module.declPtr(decl_index);
2441 if (decl.link.macho.sym_index == 0) return;2474 const atom = &decl.link.macho;
2475 try atom.ensureInitialized(self);
2476
2477 const gop = try self.decls.getOrPut(gpa, decl_index);
2478 if (!gop.found_existing) {
2479 gop.value_ptr.* = null;
2480 }
2481
2442 const decl_sym = decl.link.macho.getSymbol(self);2482 const decl_sym = decl.link.macho.getSymbol(self);
24432483
2444 for (exports) |exp| {2484 for (exports) |exp| {
...@@ -2573,11 +2613,6 @@ fn freeUnnamedConsts(self: *MachO, decl_index: Module.Decl.Index) void {...@@ -2573,11 +2613,6 @@ fn freeUnnamedConsts(self: *MachO, decl_index: Module.Decl.Index) void {
2573 const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return;2613 const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return;
2574 for (unnamed_consts.items) |atom| {2614 for (unnamed_consts.items) |atom| {
2575 self.freeAtom(atom);2615 self.freeAtom(atom);
2576 self.locals_free_list.append(gpa, atom.sym_index) catch {};
2577 self.locals.items[atom.sym_index].n_type = 0;
2578 _ = self.atom_by_index_table.remove(atom.sym_index);
2579 log.debug(" adding local symbol index {d} to free list", .{atom.sym_index});
2580 atom.sym_index = 0;
2581 }2616 }
2582 unnamed_consts.clearAndFree(gpa);2617 unnamed_consts.clearAndFree(gpa);
2583}2618}
...@@ -2591,39 +2626,11 @@ pub fn freeDecl(self: *MachO, decl_index: Module.Decl.Index) void {...@@ -2591,39 +2626,11 @@ pub fn freeDecl(self: *MachO, decl_index: Module.Decl.Index) void {
25912626
2592 log.debug("freeDecl {*}", .{decl});2627 log.debug("freeDecl {*}", .{decl});
25932628
2594 const kv = self.decls.fetchSwapRemove(decl_index);2629 if (self.decls.fetchSwapRemove(decl_index)) |kv| {
2595 if (kv.?.value) |_| {2630 if (kv.value) |_| {
2596 self.freeAtom(&decl.link.macho);2631 self.freeAtom(&decl.link.macho);
2597 self.freeUnnamedConsts(decl_index);2632 self.freeUnnamedConsts(decl_index);
2598 }
2599
2600 // Appending to free lists is allowed to fail because the free lists are heuristics based anyway.
2601 const gpa = self.base.allocator;
2602 const sym_index = decl.link.macho.sym_index;
2603 if (sym_index != 0) {
2604 self.locals_free_list.append(gpa, sym_index) catch {};
2605
2606 // Try freeing GOT atom if this decl had one
2607 const got_target = SymbolWithLoc{ .sym_index = sym_index, .file = null };
2608 if (self.got_entries_table.get(got_target)) |got_index| {
2609 self.got_entries_free_list.append(gpa, @intCast(u32, got_index)) catch {};
2610 self.got_entries.items[got_index] = .{
2611 .target = .{ .sym_index = 0, .file = null },
2612 .sym_index = 0,
2613 };
2614 _ = self.got_entries_table.remove(got_target);
2615
2616 if (self.d_sym) |*d_sym| {
2617 d_sym.swapRemoveRelocs(sym_index);
2618 }
2619
2620 log.debug(" adding GOT index {d} to free list (target local@{d})", .{ got_index, sym_index });
2621 }2633 }
2622
2623 self.locals.items[sym_index].n_type = 0;
2624 _ = self.atom_by_index_table.remove(sym_index);
2625 log.debug(" adding local symbol index {d} to free list", .{sym_index});
2626 decl.link.macho.sym_index = 0;
2627 }2634 }
26282635
2629 if (self.d_sym) |*d_sym| {2636 if (self.d_sym) |*d_sym| {
...@@ -2636,7 +2643,9 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil...@@ -2636,7 +2643,9 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil
2636 const decl = mod.declPtr(decl_index);2643 const decl = mod.declPtr(decl_index);
26372644
2638 assert(self.llvm_object == null);2645 assert(self.llvm_object == null);
2639 assert(decl.link.macho.sym_index != 0);2646
2647 try decl.link.macho.ensureInitialized(self);
2648 const sym_index = decl.link.macho.getSymbolIndex().?;
26402649
2641 const atom = self.getAtomForSymbol(.{ .sym_index = reloc_info.parent_atom_index, .file = null }).?;2650 const atom = self.getAtomForSymbol(.{ .sym_index = reloc_info.parent_atom_index, .file = null }).?;
2642 try atom.addRelocation(self, .{2651 try atom.addRelocation(self, .{
...@@ -2645,7 +2654,7 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil...@@ -2645,7 +2654,7 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil
2645 .x86_64 => @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_UNSIGNED),2654 .x86_64 => @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_UNSIGNED),
2646 else => unreachable,2655 else => unreachable,
2647 },2656 },
2648 .target = .{ .sym_index = decl.link.macho.sym_index, .file = null },2657 .target = .{ .sym_index = sym_index, .file = null },
2649 .offset = @intCast(u32, reloc_info.offset),2658 .offset = @intCast(u32, reloc_info.offset),
2650 .addend = reloc_info.addend,2659 .addend = reloc_info.addend,
2651 .pcrel = false,2660 .pcrel = false,
...@@ -3179,7 +3188,7 @@ fn collectRebaseData(self: *MachO, rebase: *Rebase) !void {...@@ -3179,7 +3188,7 @@ fn collectRebaseData(self: *MachO, rebase: *Rebase) !void {
3179 const slice = self.sections.slice();3188 const slice = self.sections.slice();
31803189
3181 for (self.rebases.keys()) |atom, i| {3190 for (self.rebases.keys()) |atom, i| {
3182 log.debug(" ATOM(%{d}, '{s}')", .{ atom.sym_index, atom.getName(self) });3191 log.debug(" ATOM(%{?d}, '{s}')", .{ atom.getSymbolIndex(), atom.getName(self) });
31833192
3184 const sym = atom.getSymbol(self);3193 const sym = atom.getSymbol(self);
3185 const segment_index = slice.items(.segment_index)[sym.n_sect - 1];3194 const segment_index = slice.items(.segment_index)[sym.n_sect - 1];
...@@ -3208,7 +3217,7 @@ fn collectBindData(self: *MachO, bind: anytype, raw_bindings: anytype) !void {...@@ -3208,7 +3217,7 @@ fn collectBindData(self: *MachO, bind: anytype, raw_bindings: anytype) !void {
3208 const slice = self.sections.slice();3217 const slice = self.sections.slice();
32093218
3210 for (raw_bindings.keys()) |atom, i| {3219 for (raw_bindings.keys()) |atom, i| {
3211 log.debug(" ATOM(%{d}, '{s}')", .{ atom.sym_index, atom.getName(self) });3220 log.debug(" ATOM(%{?d}, '{s}')", .{ atom.getSymbolIndex(), atom.getName(self) });
32123221
3213 const sym = atom.getSymbol(self);3222 const sym = atom.getSymbol(self);
3214 const segment_index = slice.items(.segment_index)[sym.n_sect - 1];3223 const segment_index = slice.items(.segment_index)[sym.n_sect - 1];
...@@ -4277,8 +4286,8 @@ pub fn logAtoms(self: *MachO) void {...@@ -4277,8 +4286,8 @@ pub fn logAtoms(self: *MachO) void {
4277pub fn logAtom(self: *MachO, atom: *const Atom) void {4286pub fn logAtom(self: *MachO, atom: *const Atom) void {
4278 const sym = atom.getSymbol(self);4287 const sym = atom.getSymbol(self);
4279 const sym_name = atom.getName(self);4288 const sym_name = atom.getName(self);
4280 log.debug(" ATOM(%{d}, '{s}') @ {x} (sizeof({x}), alignof({x})) in object({?d}) in sect({d})", .{4289 log.debug(" ATOM(%{?d}, '{s}') @ {x} (sizeof({x}), alignof({x})) in object({?d}) in sect({d})", .{
4281 atom.sym_index,4290 atom.getSymbolIndex(),
4282 sym_name,4291 sym_name,
4283 sym.n_value,4292 sym.n_value,
4284 atom.size,4293 atom.size,
src/link/MachO/Atom.zig+22-8
...@@ -64,6 +64,17 @@ pub const empty = Atom{...@@ -64,6 +64,17 @@ pub const empty = Atom{
64 .dbg_info_atom = undefined,64 .dbg_info_atom = undefined,
65};65};
6666
67pub fn ensureInitialized(self: *Atom, macho_file: *MachO) !void {
68 if (self.getSymbolIndex() != null) return; // Already initialized
69 self.sym_index = try macho_file.allocateSymbol();
70 try macho_file.atom_by_index_table.putNoClobber(macho_file.base.allocator, self.sym_index, self);
71}
72
73pub fn getSymbolIndex(self: Atom) ?u32 {
74 if (self.sym_index == 0) return null;
75 return self.sym_index;
76}
77
67/// Returns symbol referencing this atom.78/// Returns symbol referencing this atom.
68pub fn getSymbol(self: Atom, macho_file: *MachO) macho.nlist_64 {79pub fn getSymbol(self: Atom, macho_file: *MachO) macho.nlist_64 {
69 return self.getSymbolPtr(macho_file).*;80 return self.getSymbolPtr(macho_file).*;
...@@ -71,20 +82,23 @@ pub fn getSymbol(self: Atom, macho_file: *MachO) macho.nlist_64 {...@@ -71,20 +82,23 @@ pub fn getSymbol(self: Atom, macho_file: *MachO) macho.nlist_64 {
7182
72/// Returns pointer-to-symbol referencing this atom.83/// Returns pointer-to-symbol referencing this atom.
73pub fn getSymbolPtr(self: Atom, macho_file: *MachO) *macho.nlist_64 {84pub fn getSymbolPtr(self: Atom, macho_file: *MachO) *macho.nlist_64 {
85 const sym_index = self.getSymbolIndex().?;
74 return macho_file.getSymbolPtr(.{86 return macho_file.getSymbolPtr(.{
75 .sym_index = self.sym_index,87 .sym_index = sym_index,
76 .file = self.file,88 .file = self.file,
77 });89 });
78}90}
7991
80pub fn getSymbolWithLoc(self: Atom) SymbolWithLoc {92pub fn getSymbolWithLoc(self: Atom) SymbolWithLoc {
81 return .{ .sym_index = self.sym_index, .file = self.file };93 const sym_index = self.getSymbolIndex().?;
94 return .{ .sym_index = sym_index, .file = self.file };
82}95}
8396
84/// Returns the name of this atom.97/// Returns the name of this atom.
85pub fn getName(self: Atom, macho_file: *MachO) []const u8 {98pub fn getName(self: Atom, macho_file: *MachO) []const u8 {
99 const sym_index = self.getSymbolIndex().?;
86 return macho_file.getSymbolName(.{100 return macho_file.getSymbolName(.{
87 .sym_index = self.sym_index,101 .sym_index = sym_index,
88 .file = self.file,102 .file = self.file,
89 });103 });
90}104}
...@@ -144,7 +158,7 @@ pub fn addRelocations(...@@ -144,7 +158,7 @@ pub fn addRelocations(
144158
145pub fn addRebase(self: *Atom, macho_file: *MachO, offset: u32) !void {159pub fn addRebase(self: *Atom, macho_file: *MachO, offset: u32) !void {
146 const gpa = macho_file.base.allocator;160 const gpa = macho_file.base.allocator;
147 log.debug(" (adding rebase at offset 0x{x} in %{d})", .{ offset, self.sym_index });161 log.debug(" (adding rebase at offset 0x{x} in %{?d})", .{ offset, self.getSymbolIndex() });
148 const gop = try macho_file.rebases.getOrPut(gpa, self);162 const gop = try macho_file.rebases.getOrPut(gpa, self);
149 if (!gop.found_existing) {163 if (!gop.found_existing) {
150 gop.value_ptr.* = .{};164 gop.value_ptr.* = .{};
...@@ -154,10 +168,10 @@ pub fn addRebase(self: *Atom, macho_file: *MachO, offset: u32) !void {...@@ -154,10 +168,10 @@ pub fn addRebase(self: *Atom, macho_file: *MachO, offset: u32) !void {
154168
155pub fn addBinding(self: *Atom, macho_file: *MachO, binding: Binding) !void {169pub fn addBinding(self: *Atom, macho_file: *MachO, binding: Binding) !void {
156 const gpa = macho_file.base.allocator;170 const gpa = macho_file.base.allocator;
157 log.debug(" (adding binding to symbol {s} at offset 0x{x} in %{d})", .{171 log.debug(" (adding binding to symbol {s} at offset 0x{x} in %{?d})", .{
158 macho_file.getSymbolName(binding.target),172 macho_file.getSymbolName(binding.target),
159 binding.offset,173 binding.offset,
160 self.sym_index,174 self.getSymbolIndex(),
161 });175 });
162 const gop = try macho_file.bindings.getOrPut(gpa, self);176 const gop = try macho_file.bindings.getOrPut(gpa, self);
163 if (!gop.found_existing) {177 if (!gop.found_existing) {
...@@ -168,10 +182,10 @@ pub fn addBinding(self: *Atom, macho_file: *MachO, binding: Binding) !void {...@@ -168,10 +182,10 @@ pub fn addBinding(self: *Atom, macho_file: *MachO, binding: Binding) !void {
168182
169pub fn addLazyBinding(self: *Atom, macho_file: *MachO, binding: Binding) !void {183pub fn addLazyBinding(self: *Atom, macho_file: *MachO, binding: Binding) !void {
170 const gpa = macho_file.base.allocator;184 const gpa = macho_file.base.allocator;
171 log.debug(" (adding lazy binding to symbol {s} at offset 0x{x} in %{d})", .{185 log.debug(" (adding lazy binding to symbol {s} at offset 0x{x} in %{?d})", .{
172 macho_file.getSymbolName(binding.target),186 macho_file.getSymbolName(binding.target),
173 binding.offset,187 binding.offset,
174 self.sym_index,188 self.getSymbolIndex(),
175 });189 });
176 const gop = try macho_file.lazy_bindings.getOrPut(gpa, self);190 const gop = try macho_file.lazy_bindings.getOrPut(gpa, self);
177 if (!gop.found_existing) {191 if (!gop.found_existing) {