authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-09-10 09:07:07+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-09-10 09:07:07+02:00
log69da56b36c1bd23214b9c72587cdd424637d2ced
tree7a89fa64057fae83b41de04f4b16f16505655957
parent5b9c5191ab919f4166a9e0c4486bd57bb2533791
parenta1b8545265b4fb47fe45287655f8885d092aa9df
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #12802 from ziglang/macho-refactor

Self-hosted backends and linkers refactor: x86_64 + aarch64 + macho + coff

10 files changed, 365 insertions(+), 397 deletions(-)

src/arch/aarch64/CodeGen.zig+35-50
......@@ -139,21 +139,10 @@ const MCValue = union(enum) {
139139 /// If the type is a pointer, it means the pointer address is at
140140 /// this memory location.
141141 memory: u64,
142 /// The value is in memory referenced indirectly via a GOT entry
143 /// index.
144 ///
145 /// If the type is a pointer, it means the pointer is referenced
146 /// indirectly via GOT. When lowered, linker will emit
147 /// relocations of type ARM64_RELOC_GOT_LOAD_PAGE21 and
148 /// ARM64_RELOC_GOT_LOAD_PAGEOFF12.
149 got_load: u32,
150 /// The value is in memory referenced directly via symbol index.
151 ///
152 /// If the type is a pointer, it means the pointer is referenced
153 /// directly via symbol index. When lowered, linker will emit a
154 /// relocation of type ARM64_RELOC_PAGE21 and
155 /// ARM64_RELOC_PAGEOFF12.
156 direct_load: u32,
142 /// The value is in memory but requires a linker relocation fixup:
143 /// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc)
144 /// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc)
145 linker_load: struct { @"type": enum { got, direct }, sym_index: u32 },
157146 /// The value is one of the stack variables.
158147 ///
159148 /// If the type is a pointer, it means the pointer address is in
......@@ -2959,8 +2948,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
29592948 .memory,
29602949 .stack_offset,
29612950 .stack_argument_offset,
2962 .got_load,
2963 .direct_load,
2951 .linker_load,
29642952 => {
29652953 const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr);
29662954 try self.load(dst_mcv, .{ .register = addr_reg }, ptr_ty);
......@@ -3197,8 +3185,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
31973185 .memory,
31983186 .stack_offset,
31993187 .stack_argument_offset,
3200 .got_load,
3201 .direct_load,
3188 .linker_load,
32023189 => {
32033190 const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr);
32043191 try self.store(.{ .register = addr_reg }, value, ptr_ty, value_ty);
......@@ -3493,7 +3480,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
34933480 const func = func_payload.data;
34943481 const fn_owner_decl = mod.declPtr(func.owner_decl);
34953482 try self.genSetReg(Type.initTag(.u64), .x30, .{
3496 .got_load = fn_owner_decl.link.macho.sym_index,
3483 .linker_load = .{
3484 .@"type" = .got,
3485 .sym_index = fn_owner_decl.link.macho.sym_index,
3486 },
34973487 });
34983488 // blr x30
34993489 _ = try self.addInst(.{
......@@ -4427,8 +4417,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
44274417 .register = cond_reg,
44284418 });
44294419 },
4430 .got_load,
4431 .direct_load,
4420 .linker_load,
44324421 .memory,
44334422 .stack_argument_offset,
44344423 .stack_offset,
......@@ -4479,13 +4468,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
44794468 });
44804469 },
44814470 .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = addr }),
4482 .got_load,
4483 .direct_load,
4484 => |sym_index| {
4485 const tag: Mir.Inst.Tag = switch (mcv) {
4486 .got_load => .load_memory_ptr_got,
4487 .direct_load => .load_memory_ptr_direct,
4488 else => unreachable,
4471 .linker_load => |load_struct| {
4472 const tag: Mir.Inst.Tag = switch (load_struct.@"type") {
4473 .got => .load_memory_ptr_got,
4474 .direct => .load_memory_ptr_direct,
44894475 };
44904476 const mod = self.bin_file.options.module.?;
44914477 _ = try self.addInst(.{
......@@ -4494,7 +4480,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
44944480 .payload = try self.addExtra(Mir.LoadMemoryPie{
44954481 .register = @enumToInt(src_reg),
44964482 .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.sym_index,
4497 .sym_index = sym_index,
4483 .sym_index = load_struct.sym_index,
44984484 }),
44994485 },
45004486 });
......@@ -4594,13 +4580,10 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
45944580 });
45954581 },
45964582 .register_with_overflow => unreachable, // doesn't fit into a register
4597 .got_load,
4598 .direct_load,
4599 => |sym_index| {
4600 const tag: Mir.Inst.Tag = switch (mcv) {
4601 .got_load => .load_memory_got,
4602 .direct_load => .load_memory_direct,
4603 else => unreachable,
4583 .linker_load => |load_struct| {
4584 const tag: Mir.Inst.Tag = switch (load_struct.@"type") {
4585 .got => .load_memory_got,
4586 .direct => .load_memory_direct,
46044587 };
46054588 const mod = self.bin_file.options.module.?;
46064589 _ = try self.addInst(.{
......@@ -4609,7 +4592,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
46094592 .payload = try self.addExtra(Mir.LoadMemoryPie{
46104593 .register = @enumToInt(reg),
46114594 .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.sym_index,
4612 .sym_index = sym_index,
4595 .sym_index = load_struct.sym_index,
46134596 }),
46144597 },
46154598 });
......@@ -4741,8 +4724,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
47414724 .register_with_overflow => {
47424725 return self.fail("TODO implement genSetStackArgument {}", .{mcv});
47434726 },
4744 .got_load,
4745 .direct_load,
4727 .linker_load,
47464728 .memory,
47474729 .stack_argument_offset,
47484730 .stack_offset,
......@@ -4785,13 +4767,10 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
47854767 });
47864768 },
47874769 .memory => |addr| try self.genSetReg(ptr_ty, src_reg, .{ .immediate = @intCast(u32, addr) }),
4788 .got_load,
4789 .direct_load,
4790 => |sym_index| {
4791 const tag: Mir.Inst.Tag = switch (mcv) {
4792 .got_load => .load_memory_ptr_got,
4793 .direct_load => .load_memory_ptr_direct,
4794 else => unreachable,
4770 .linker_load => |load_struct| {
4771 const tag: Mir.Inst.Tag = switch (load_struct.@"type") {
4772 .got => .load_memory_ptr_got,
4773 .direct => .load_memory_ptr_direct,
47954774 };
47964775 const mod = self.bin_file.options.module.?;
47974776 _ = try self.addInst(.{
......@@ -4800,7 +4779,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
48004779 .payload = try self.addExtra(Mir.LoadMemoryPie{
48014780 .register = @enumToInt(src_reg),
48024781 .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.sym_index,
4803 .sym_index = sym_index,
4782 .sym_index = load_struct.sym_index,
48044783 }),
48054784 },
48064785 });
......@@ -5107,7 +5086,10 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
51075086 // Because MachO is PIE-always-on, we defer memory address resolution until
51085087 // the linker has enough info to perform relocations.
51095088 assert(decl.link.macho.sym_index != 0);
5110 return MCValue{ .got_load = decl.link.macho.sym_index };
5089 return MCValue{ .linker_load = .{
5090 .@"type" = .got,
5091 .sym_index = decl.link.macho.sym_index,
5092 } };
51115093 } else if (self.bin_file.cast(link.File.Coff)) |_| {
51125094 return self.fail("TODO codegen COFF const Decl pointer", .{});
51135095 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
......@@ -5129,7 +5111,10 @@ fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue {
51295111 const vaddr = elf_file.local_symbols.items[local_sym_index].st_value;
51305112 return MCValue{ .memory = vaddr };
51315113 } else if (self.bin_file.cast(link.File.MachO)) |_| {
5132 return MCValue{ .direct_load = local_sym_index };
5114 return MCValue{ .linker_load = .{
5115 .@"type" = .direct,
5116 .sym_index = local_sym_index,
5117 } };
51335118 } else if (self.bin_file.cast(link.File.Coff)) |_| {
51345119 return self.fail("TODO lower unnamed const in COFF", .{});
51355120 } else if (self.bin_file.cast(link.File.Plan9)) |_| {
src/arch/aarch64/Emit.zig+2-4
......@@ -681,12 +681,10 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void {
681681 };
682682 // Add relocation to the decl.
683683 const atom = macho_file.atom_by_index_table.get(relocation.atom_index).?;
684 const target = macho_file.getGlobalByIndex(relocation.sym_index);
684685 try atom.relocs.append(emit.bin_file.allocator, .{
685686 .offset = offset,
686 .target = .{
687 .sym_index = relocation.sym_index,
688 .file = null,
689 },
687 .target = target,
690688 .addend = 0,
691689 .subtractor = null,
692690 .pcrel = true,
src/arch/x86_64/CodeGen.zig+67-141
......@@ -128,15 +128,11 @@ pub const MCValue = union(enum) {
128128 /// The value is in memory at a hard-coded address.
129129 /// If the type is a pointer, it means the pointer address is at this memory location.
130130 memory: u64,
131 /// The value is in memory referenced indirectly via a GOT entry index.
132 /// If the type is a pointer, it means the pointer is referenced indirectly via GOT.
133 /// When lowered, linker will emit a relocation of type X86_64_RELOC_GOT.
134 got_load: u32,
135 imports_load: u32,
136 /// The value is in memory referenced directly via symbol index.
137 /// If the type is a pointer, it means the pointer is referenced directly via symbol index.
138 /// When lowered, linker will emit a relocation of type X86_64_RELOC_SIGNED.
139 direct_load: u32,
131 /// The value is in memory but requires a linker relocation fixup:
132 /// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc)
133 /// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc)
134 /// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc)
135 linker_load: struct { @"type": enum { got, direct, import }, sym_index: u32 },
140136 /// The value is one of the stack variables.
141137 /// If the type is a pointer, it means the pointer address is in the stack at this offset.
142138 stack_offset: i32,
......@@ -150,9 +146,7 @@ pub const MCValue = union(enum) {
150146 .memory,
151147 .stack_offset,
152148 .ptr_stack_offset,
153 .direct_load,
154 .got_load,
155 .imports_load,
149 .linker_load,
156150 => true,
157151 else => false,
158152 };
......@@ -165,26 +159,6 @@ pub const MCValue = union(enum) {
165159 };
166160 }
167161
168 fn isMutable(mcv: MCValue) bool {
169 return switch (mcv) {
170 .none => unreachable,
171 .unreach => unreachable,
172 .dead => unreachable,
173
174 .immediate,
175 .memory,
176 .eflags,
177 .ptr_stack_offset,
178 .undef,
179 .register_overflow,
180 => false,
181
182 .register,
183 .stack_offset,
184 => true,
185 };
186 }
187
188162 fn isRegister(mcv: MCValue) bool {
189163 return switch (mcv) {
190164 .register => true,
......@@ -2307,11 +2281,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
23072281 .data = .{ .imm = @bitCast(u32, -off) },
23082282 });
23092283 },
2310 .memory,
2311 .got_load,
2312 .direct_load,
2313 .imports_load,
2314 => {
2284 .memory, .linker_load => {
23152285 try self.loadMemPtrIntoRegister(addr_reg, Type.usize, array);
23162286 },
23172287 else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),
......@@ -2652,11 +2622,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
26522622 else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}),
26532623 }
26542624 },
2655 .memory,
2656 .got_load,
2657 .direct_load,
2658 .imports_load,
2659 => {
2625 .memory, .linker_load => {
26602626 const reg = try self.copyToTmpRegister(ptr_ty, ptr);
26612627 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);
26622628 },
......@@ -2691,10 +2657,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
26912657
26922658fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue) InnerError!void {
26932659 switch (ptr) {
2694 .got_load,
2695 .direct_load,
2696 .imports_load,
2697 => |sym_index| {
2660 .linker_load => |load_struct| {
26982661 const abi_size = @intCast(u32, ptr_ty.abiSize(self.target.*));
26992662 const mod = self.bin_file.options.module.?;
27002663 const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl);
......@@ -2702,11 +2665,10 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue
27022665 fn_owner_decl.link.macho.sym_index
27032666 else
27042667 fn_owner_decl.link.coff.sym_index;
2705 const flags: u2 = switch (ptr) {
2706 .got_load => 0b00,
2707 .direct_load => 0b01,
2708 .imports_load => 0b10,
2709 else => unreachable,
2668 const flags: u2 = switch (load_struct.@"type") {
2669 .got => 0b00,
2670 .direct => 0b01,
2671 .import => 0b10,
27102672 };
27112673 _ = try self.addInst(.{
27122674 .tag = .lea_pic,
......@@ -2717,7 +2679,7 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue
27172679 .data = .{
27182680 .relocation = .{
27192681 .atom_index = atom_index,
2720 .sym_index = sym_index,
2682 .sym_index = load_struct.sym_index,
27212683 },
27222684 },
27232685 });
......@@ -2801,9 +2763,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
28012763 .register => |src_reg| {
28022764 try self.genInlineMemcpyRegisterRegister(value_ty, reg, src_reg, 0);
28032765 },
2804 .got_load,
2805 .direct_load,
2806 .imports_load,
2766 .linker_load,
28072767 .memory,
28082768 .stack_offset,
28092769 => {
......@@ -2822,11 +2782,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
28222782 },
28232783 }
28242784 },
2825 .got_load,
2826 .direct_load,
2827 .imports_load,
2828 .memory,
2829 => {
2785 .linker_load, .memory => {
28302786 const value_lock: ?RegisterLock = switch (value) {
28312787 .register => |reg| self.register_manager.lockReg(reg),
28322788 else => null,
......@@ -2894,11 +2850,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
28942850 .register => {
28952851 return self.store(new_ptr, value, ptr_ty, value_ty);
28962852 },
2897 .got_load,
2898 .direct_load,
2899 .imports_load,
2900 .memory,
2901 => {
2853 .linker_load, .memory => {
29022854 if (abi_size <= 8) {
29032855 const tmp_reg = try self.register_manager.allocReg(null, gp);
29042856 const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
......@@ -3606,9 +3558,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu
36063558 });
36073559 },
36083560 .memory,
3609 .got_load,
3610 .direct_load,
3611 .imports_load,
3561 .linker_load,
36123562 .eflags,
36133563 => {
36143564 assert(abi_size <= 8);
......@@ -3694,10 +3644,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu
36943644 => {
36953645 return self.fail("TODO implement x86 ADD/SUB/CMP source memory", .{});
36963646 },
3697 .got_load,
3698 .direct_load,
3699 .imports_load,
3700 => {
3647 .linker_load => {
37013648 return self.fail("TODO implement x86 ADD/SUB/CMP source symbol at index in linker", .{});
37023649 },
37033650 .eflags => {
......@@ -3708,10 +3655,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu
37083655 .memory => {
37093656 return self.fail("TODO implement x86 ADD/SUB/CMP destination memory", .{});
37103657 },
3711 .got_load,
3712 .direct_load,
3713 .imports_load,
3714 => {
3658 .linker_load => {
37153659 return self.fail("TODO implement x86 ADD/SUB/CMP destination symbol at index", .{});
37163660 },
37173661 }
......@@ -3779,10 +3723,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
37793723 .memory => {
37803724 return self.fail("TODO implement x86 multiply source memory", .{});
37813725 },
3782 .got_load,
3783 .direct_load,
3784 .imports_load,
3785 => {
3726 .linker_load => {
37863727 return self.fail("TODO implement x86 multiply source symbol at index in linker", .{});
37873728 },
37883729 .eflags => {
......@@ -3826,10 +3767,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
38263767 .memory, .stack_offset => {
38273768 return self.fail("TODO implement x86 multiply source memory", .{});
38283769 },
3829 .got_load,
3830 .direct_load,
3831 .imports_load,
3832 => {
3770 .linker_load => {
38333771 return self.fail("TODO implement x86 multiply source symbol at index in linker", .{});
38343772 },
38353773 .eflags => {
......@@ -3840,10 +3778,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
38403778 .memory => {
38413779 return self.fail("TODO implement x86 multiply destination memory", .{});
38423780 },
3843 .got_load,
3844 .direct_load,
3845 .imports_load,
3846 => {
3781 .linker_load => {
38473782 return self.fail("TODO implement x86 multiply destination symbol at index in linker", .{});
38483783 },
38493784 }
......@@ -4006,9 +3941,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
40063941 .unreach => unreachable,
40073942 .dead => unreachable,
40083943 .memory => unreachable,
4009 .got_load => unreachable,
4010 .direct_load => unreachable,
4011 .imports_load => unreachable,
3944 .linker_load => unreachable,
40123945 .eflags => unreachable,
40133946 .register_overflow => unreachable,
40143947 }
......@@ -4066,7 +3999,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
40663999 const func = func_payload.data;
40674000 const fn_owner_decl = mod.declPtr(func.owner_decl);
40684001 try self.genSetReg(Type.initTag(.usize), .rax, .{
4069 .got_load = fn_owner_decl.link.coff.sym_index,
4002 .linker_load = .{
4003 .@"type" = .got,
4004 .sym_index = fn_owner_decl.link.coff.sym_index,
4005 },
40704006 });
40714007 _ = try self.addInst(.{
40724008 .tag = .call,
......@@ -4087,7 +4023,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
40874023 }
40884024 const sym_index = try coff_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));
40894025 try self.genSetReg(Type.initTag(.usize), .rax, .{
4090 .imports_load = sym_index,
4026 .linker_load = .{
4027 .@"type" = .import,
4028 .sym_index = sym_index,
4029 },
40914030 });
40924031 _ = try self.addInst(.{
40934032 .tag = .call,
......@@ -4119,7 +4058,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
41194058 const func = func_payload.data;
41204059 const fn_owner_decl = mod.declPtr(func.owner_decl);
41214060 const sym_index = fn_owner_decl.link.macho.sym_index;
4122 try self.genSetReg(Type.initTag(.usize), .rax, .{ .got_load = sym_index });
4061 try self.genSetReg(Type.initTag(.usize), .rax, .{
4062 .linker_load = .{
4063 .@"type" = .got,
4064 .sym_index = sym_index,
4065 },
4066 });
41234067 // callq *%rax
41244068 _ = try self.addInst(.{
41254069 .tag = .call,
......@@ -4505,11 +4449,7 @@ fn genVarDbgInfo(
45054449 leb128.writeILEB128(dbg_info.writer(), -off) catch unreachable;
45064450 dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
45074451 },
4508 .memory,
4509 .got_load,
4510 .direct_load,
4511 .imports_load,
4512 => {
4452 .memory, .linker_load => {
45134453 const ptr_width = @intCast(u8, @divExact(self.target.cpu.arch.ptrBitWidth(), 8));
45144454 const is_ptr = switch (tag) {
45154455 .dbg_var_ptr => true,
......@@ -4540,10 +4480,11 @@ fn genVarDbgInfo(
45404480 try dbg_info.append(DW.OP.deref);
45414481 }
45424482 switch (mcv) {
4543 .got_load,
4544 .direct_load,
4545 .imports_load,
4546 => |index| try dw.addExprlocReloc(index, offset, is_ptr),
4483 .linker_load => |load_struct| try dw.addExprlocReloc(
4484 load_struct.sym_index,
4485 offset,
4486 is_ptr,
4487 ),
45474488 else => {},
45484489 }
45494490 },
......@@ -5587,11 +5528,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
55875528 else => return self.fail("TODO implement inputs on stack for {} with abi size > 8", .{mcv}),
55885529 }
55895530 },
5590 .memory,
5591 .direct_load,
5592 .got_load,
5593 .imports_load,
5594 => {
5531 .memory, .linker_load => {
55955532 if (abi_size <= 8) {
55965533 const reg = try self.copyToTmpRegister(ty, mcv);
55975534 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
......@@ -5835,11 +5772,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
58355772 },
58365773 }
58375774 },
5838 .memory,
5839 .got_load,
5840 .direct_load,
5841 .imports_load,
5842 => {
5775 .memory, .linker_load => {
58435776 if (abi_size <= 8) {
58445777 const reg = try self.copyToTmpRegister(ty, mcv);
58455778 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }, opts);
......@@ -5959,11 +5892,7 @@ fn genInlineMemcpy(
59595892 const tmp_reg = regs[4].to8();
59605893
59615894 switch (dst_ptr) {
5962 .memory,
5963 .got_load,
5964 .direct_load,
5965 .imports_load,
5966 => {
5895 .memory, .linker_load => {
59675896 try self.loadMemPtrIntoRegister(dst_addr_reg, Type.usize, dst_ptr);
59685897 },
59695898 .ptr_stack_offset, .stack_offset => |off| {
......@@ -5992,11 +5921,7 @@ fn genInlineMemcpy(
59925921 }
59935922
59945923 switch (src_ptr) {
5995 .memory,
5996 .got_load,
5997 .direct_load,
5998 .imports_load,
5999 => {
5924 .memory, .linker_load => {
60005925 try self.loadMemPtrIntoRegister(src_addr_reg, Type.usize, src_ptr);
60015926 },
60025927 .ptr_stack_offset, .stack_offset => |off| {
......@@ -6120,11 +6045,7 @@ fn genInlineMemset(
61206045 const index_reg = regs[1].to64();
61216046
61226047 switch (dst_ptr) {
6123 .memory,
6124 .got_load,
6125 .direct_load,
6126 .imports_load,
6127 => {
6048 .memory, .linker_load => {
61286049 try self.loadMemPtrIntoRegister(addr_reg, Type.usize, dst_ptr);
61296050 },
61306051 .ptr_stack_offset, .stack_offset => |off| {
......@@ -6356,10 +6277,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
63566277 .data = undefined,
63576278 });
63586279 },
6359 .direct_load,
6360 .got_load,
6361 .imports_load,
6362 => {
6280 .linker_load => {
63636281 switch (ty.zigTypeTag()) {
63646282 .Float => {
63656283 const base_reg = try self.register_manager.allocReg(null, gp);
......@@ -6753,11 +6671,7 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
67536671 // TODO Is this the only condition for pointer dereference for memcpy?
67546672 const src: MCValue = blk: {
67556673 switch (src_ptr) {
6756 .got_load,
6757 .direct_load,
6758 .imports_load,
6759 .memory,
6760 => {
6674 .linker_load, .memory => {
67616675 const reg = try self.register_manager.allocReg(null, gp);
67626676 try self.loadMemPtrIntoRegister(reg, src_ty, src_ptr);
67636677 _ = try self.addInst(.{
......@@ -6997,10 +6911,16 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
69976911 return MCValue{ .memory = got_addr };
69986912 } else if (self.bin_file.cast(link.File.MachO)) |_| {
69996913 assert(decl.link.macho.sym_index != 0);
7000 return MCValue{ .got_load = decl.link.macho.sym_index };
6914 return MCValue{ .linker_load = .{
6915 .@"type" = .got,
6916 .sym_index = decl.link.macho.sym_index,
6917 } };
70016918 } else if (self.bin_file.cast(link.File.Coff)) |_| {
70026919 assert(decl.link.coff.sym_index != 0);
7003 return MCValue{ .got_load = decl.link.coff.sym_index };
6920 return MCValue{ .linker_load = .{
6921 .@"type" = .got,
6922 .sym_index = decl.link.coff.sym_index,
6923 } };
70046924 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
70056925 try p9.seeDecl(decl_index);
70066926 const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes;
......@@ -7019,9 +6939,15 @@ fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue {
70196939 const vaddr = elf_file.local_symbols.items[local_sym_index].st_value;
70206940 return MCValue{ .memory = vaddr };
70216941 } else if (self.bin_file.cast(link.File.MachO)) |_| {
7022 return MCValue{ .direct_load = local_sym_index };
6942 return MCValue{ .linker_load = .{
6943 .@"type" = .direct,
6944 .sym_index = local_sym_index,
6945 } };
70236946 } else if (self.bin_file.cast(link.File.Coff)) |_| {
7024 return MCValue{ .direct_load = local_sym_index };
6947 return MCValue{ .linker_load = .{
6948 .@"type" = .direct,
6949 .sym_index = local_sym_index,
6950 } };
70256951 } else if (self.bin_file.cast(link.File.Plan9)) |_| {
70266952 return self.fail("TODO lower unnamed const in Plan9", .{});
70276953 } else {
src/arch/x86_64/Emit.zig+11-8
......@@ -1021,10 +1021,14 @@ fn mirLeaPic(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
10211021 .@"type" = switch (ops.flags) {
10221022 0b00 => .got,
10231023 0b01 => .direct,
1024 0b10 => .imports,
1024 0b10 => .import,
1025 else => unreachable,
1026 },
1027 .target = switch (ops.flags) {
1028 0b00, 0b01 => .{ .sym_index = relocation.sym_index, .file = null },
1029 0b10 => coff_file.getGlobalByIndex(relocation.sym_index),
10251030 else => unreachable,
10261031 },
1027 .target = .{ .sym_index = relocation.sym_index, .file = null },
10281032 .offset = @intCast(u32, end_offset - 4),
10291033 .addend = 0,
10301034 .pcrel = true,
......@@ -1142,12 +1146,10 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
11421146 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
11431147 // Add relocation to the decl.
11441148 const atom = macho_file.atom_by_index_table.get(relocation.atom_index).?;
1149 const target = macho_file.getGlobalByIndex(relocation.sym_index);
11451150 try atom.relocs.append(emit.bin_file.allocator, .{
11461151 .offset = offset,
1147 .target = .{
1148 .sym_index = relocation.sym_index,
1149 .file = null,
1150 },
1152 .target = target,
11511153 .addend = 0,
11521154 .subtractor = null,
11531155 .pcrel = true,
......@@ -1157,16 +1159,17 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
11571159 } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
11581160 // Add relocation to the decl.
11591161 const atom = coff_file.atom_by_index_table.get(relocation.atom_index).?;
1162 const target = coff_file.getGlobalByIndex(relocation.sym_index);
11601163 try atom.addRelocation(coff_file, .{
11611164 .@"type" = .direct,
1162 .target = .{ .sym_index = relocation.sym_index, .file = null },
1165 .target = target,
11631166 .offset = offset,
11641167 .addend = 0,
11651168 .pcrel = true,
11661169 .length = 2,
11671170 });
11681171 } else {
1169 return emit.fail("TODO implement call_extern for linking backends different than MachO", .{});
1172 return emit.fail("TODO implement call_extern for linking backends different than MachO and COFF", .{});
11701173 }
11711174}
11721175
src/link/Coff.zig+61-18
......@@ -127,7 +127,7 @@ pub const Reloc = struct {
127127 @"type": enum {
128128 got,
129129 direct,
130 imports,
130 import,
131131 },
132132 target: SymbolWithLoc,
133133 offset: u32,
......@@ -141,7 +141,7 @@ pub const Reloc = struct {
141141 switch (self.@"type") {
142142 .got => return coff_file.getGotAtomForSymbol(self.target),
143143 .direct => return coff_file.getAtomForSymbol(self.target),
144 .imports => return coff_file.getImportAtomForSymbol(self.target),
144 .import => return coff_file.getImportAtomForSymbol(self.target),
145145 }
146146 }
147147};
......@@ -1423,23 +1423,22 @@ fn resolveGlobalSymbol(self: *Coff, current: SymbolWithLoc) !void {
14231423 const sym = self.getSymbol(current);
14241424 const sym_name = self.getSymbolName(current);
14251425
1426 const global_index = self.resolver.get(sym_name) orelse {
1427 const name = try gpa.dupe(u8, sym_name);
1428 const global_index = try self.allocateGlobal();
1429 self.globals.items[global_index] = current;
1430 try self.resolver.putNoClobber(gpa, name, global_index);
1426 const gop = try self.getOrPutGlobalPtr(sym_name);
1427 if (!gop.found_existing) {
1428 gop.value_ptr.* = current;
14311429 if (sym.section_number == .UNDEFINED) {
1432 try self.unresolved.putNoClobber(gpa, global_index, false);
1430 try self.unresolved.putNoClobber(gpa, self.getGlobalIndex(sym_name).?, false);
14331431 }
14341432 return;
1435 };
1433 }
14361434
14371435 log.debug("TODO finish resolveGlobalSymbols implementation", .{});
14381436
14391437 if (sym.section_number == .UNDEFINED) return;
14401438
1441 _ = self.unresolved.swapRemove(global_index);
1442 self.globals.items[global_index] = current;
1439 _ = self.unresolved.swapRemove(self.getGlobalIndex(sym_name).?);
1440
1441 gop.value_ptr.* = current;
14431442}
14441443
14451444pub fn flush(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !void {
......@@ -1544,25 +1543,26 @@ pub fn getDeclVAddr(
15441543}
15451544
15461545pub fn getGlobalSymbol(self: *Coff, name: []const u8) !u32 {
1547 if (self.resolver.get(name)) |global_index| {
1548 return self.globals.items[global_index].sym_index;
1546 const gop = try self.getOrPutGlobalPtr(name);
1547 const global_index = self.getGlobalIndex(name).?;
1548
1549 if (gop.found_existing) {
1550 return global_index;
15491551 }
15501552
1551 const gpa = self.base.allocator;
15521553 const sym_index = try self.allocateSymbol();
1553 const global_index = try self.allocateGlobal();
15541554 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };
1555 self.globals.items[global_index] = sym_loc;
1555 gop.value_ptr.* = sym_loc;
15561556
1557 const gpa = self.base.allocator;
15571558 const sym_name = try gpa.dupe(u8, name);
15581559 const sym = self.getSymbolPtr(sym_loc);
15591560 try self.setSymbolName(sym, sym_name);
15601561 sym.storage_class = .EXTERNAL;
15611562
1562 try self.resolver.putNoClobber(gpa, sym_name, global_index);
15631563 try self.unresolved.putNoClobber(gpa, global_index, true);
15641564
1565 return sym_index;
1565 return global_index;
15661566}
15671567
15681568pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl: *Module.Decl) !void {
......@@ -2061,6 +2061,49 @@ pub fn getSymbolName(self: *const Coff, sym_loc: SymbolWithLoc) []const u8 {
20612061 return self.strtab.get(offset).?;
20622062}
20632063
2064/// Returns pointer to the global entry for `name` if one exists.
2065pub fn getGlobalPtr(self: *Coff, name: []const u8) ?*SymbolWithLoc {
2066 const global_index = self.resolver.get(name) orelse return null;
2067 return &self.globals.items[global_index];
2068}
2069
2070/// Returns the global entry for `name` if one exists.
2071pub fn getGlobal(self: *const Coff, name: []const u8) ?SymbolWithLoc {
2072 const global_index = self.resolver.get(name) orelse return null;
2073 return self.globals.items[global_index];
2074}
2075
2076/// Returns the index of the global entry for `name` if one exists.
2077pub fn getGlobalIndex(self: *const Coff, name: []const u8) ?u32 {
2078 return self.resolver.get(name);
2079}
2080
2081/// Returns global entry at `index`.
2082pub fn getGlobalByIndex(self: *const Coff, index: u32) SymbolWithLoc {
2083 assert(index < self.globals.items.len);
2084 return self.globals.items[index];
2085}
2086
2087const GetOrPutGlobalPtrResult = struct {
2088 found_existing: bool,
2089 value_ptr: *SymbolWithLoc,
2090};
2091
2092/// Return pointer to the global entry for `name` if one exists.
2093/// Puts a new global entry for `name` if one doesn't exist, and
2094/// returns a pointer to it.
2095pub fn getOrPutGlobalPtr(self: *Coff, name: []const u8) !GetOrPutGlobalPtrResult {
2096 if (self.getGlobalPtr(name)) |ptr| {
2097 return GetOrPutGlobalPtrResult{ .found_existing = true, .value_ptr = ptr };
2098 }
2099 const gpa = self.base.allocator;
2100 const global_index = try self.allocateGlobal();
2101 const global_name = try gpa.dupe(u8, name);
2102 _ = try self.resolver.put(gpa, global_name, global_index);
2103 const ptr = &self.globals.items[global_index];
2104 return GetOrPutGlobalPtrResult{ .found_existing = false, .value_ptr = ptr };
2105}
2106
20642107/// Returns atom if there is an atom referenced by the symbol described by `sym_loc` descriptor.
20652108/// Returns null on failure.
20662109pub fn getAtomForSymbol(self: *Coff, sym_loc: SymbolWithLoc) ?*Atom {
src/link/Coff/Atom.zig-10
......@@ -111,13 +111,3 @@ pub fn addBaseRelocation(self: *Atom, coff_file: *Coff, offset: u32) !void {
111111 }
112112 try gop.value_ptr.append(gpa, offset);
113113}
114
115pub fn addBinding(self: *Atom, coff_file: *Coff, target: SymbolWithLoc) !void {
116 const gpa = coff_file.base.allocator;
117 log.debug(" (adding binding to target %{d} in %{d})", .{ target.sym_index, self.sym_index });
118 const gop = try coff_file.bindings.getOrPut(gpa, self);
119 if (!gop.found_existing) {
120 gop.value_ptr.* = .{};
121 }
122 try gop.value_ptr.append(gpa, target);
123}
src/link/MachO.zig+182-159
......@@ -131,17 +131,12 @@ la_symbol_ptr_section_index: ?u8 = null,
131131data_section_index: ?u8 = null,
132132
133133locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
134globals: std.StringArrayHashMapUnmanaged(SymbolWithLoc) = .{},
135// FIXME Jakub
136// TODO storing index into globals might be dangerous if we delete a global
137// while not having everything resolved. Actually, perhaps `unresolved`
138// should not be stored at the global scope? Is this possible?
139// Otherwise, audit if this can be a problem.
140// An alternative, which I still need to investigate for perf reasons is to
141// store all global names in an adapted with context strtab.
134globals: std.ArrayListUnmanaged(SymbolWithLoc) = .{},
135resolver: std.StringHashMapUnmanaged(u32) = .{},
142136unresolved: std.AutoArrayHashMapUnmanaged(u32, bool) = .{},
143137
144138locals_free_list: std.ArrayListUnmanaged(u32) = .{},
139globals_free_list: std.ArrayListUnmanaged(u32) = .{},
145140
146141dyld_stub_binder_index: ?u32 = null,
147142dyld_private_atom: ?*Atom = null,
......@@ -1917,7 +1912,7 @@ fn allocateSpecialSymbols(self: *MachO) !void {
19171912 "___dso_handle",
19181913 "__mh_execute_header",
19191914 }) |name| {
1920 const global = self.globals.get(name) orelse continue;
1915 const global = self.getGlobal(name) orelse continue;
19211916 if (global.file != null) continue;
19221917 const sym = self.getSymbolPtr(global);
19231918 const seg = self.segments.items[self.text_segment_cmd_index.?];
......@@ -2048,16 +2043,11 @@ fn writeAtomsIncremental(self: *MachO) !void {
20482043
20492044pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !*Atom {
20502045 const gpa = self.base.allocator;
2051 const sym_index = @intCast(u32, self.locals.items.len);
2052 try self.locals.append(gpa, .{
2053 .n_strx = 0,
2054 .n_type = macho.N_SECT,
2055 .n_sect = 0,
2056 .n_desc = 0,
2057 .n_value = 0,
2058 });
2059
2046 const sym_index = try self.allocateSymbol();
20602047 const atom = try MachO.createEmptyAtom(gpa, sym_index, @sizeOf(u64), 3);
2048 const sym = atom.getSymbolPtr(self);
2049 sym.n_type = macho.N_SECT;
2050
20612051 try atom.relocs.append(gpa, .{
20622052 .offset = 0,
20632053 .target = target,
......@@ -2074,7 +2064,7 @@ pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !*Atom {
20742064
20752065 const target_sym = self.getSymbol(target);
20762066 if (target_sym.undf()) {
2077 const global = self.globals.get(self.getSymbolName(target)).?;
2067 const global = self.getGlobal(self.getSymbolName(target)).?;
20782068 try atom.bindings.append(gpa, .{
20792069 .target = global,
20802070 .offset = 0,
......@@ -2093,20 +2083,15 @@ pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !*Atom {
20932083
20942084pub fn createTlvPtrAtom(self: *MachO, target: SymbolWithLoc) !*Atom {
20952085 const gpa = self.base.allocator;
2096 const sym_index = @intCast(u32, self.locals.items.len);
2097 try self.locals.append(gpa, .{
2098 .n_strx = 0,
2099 .n_type = macho.N_SECT,
2100 .n_sect = 0,
2101 .n_desc = 0,
2102 .n_value = 0,
2103 });
2104
2086 const sym_index = try self.allocateSymbol();
21052087 const atom = try MachO.createEmptyAtom(gpa, sym_index, @sizeOf(u64), 3);
2088 const sym = atom.getSymbolPtr(self);
2089 sym.n_type = macho.N_SECT;
2090
21062091 const target_sym = self.getSymbol(target);
21072092 assert(target_sym.undf());
21082093
2109 const global = self.globals.get(self.getSymbolName(target)).?;
2094 const global = self.getGlobal(self.getSymbolName(target)).?;
21102095 try atom.bindings.append(gpa, .{
21112096 .target = global,
21122097 .offset = 0,
......@@ -2130,15 +2115,10 @@ fn createDyldPrivateAtom(self: *MachO) !void {
21302115 if (self.dyld_private_atom != null) return;
21312116
21322117 const gpa = self.base.allocator;
2133 const sym_index = @intCast(u32, self.locals.items.len);
2134 try self.locals.append(gpa, .{
2135 .n_strx = 0,
2136 .n_type = macho.N_SECT,
2137 .n_sect = 0,
2138 .n_desc = 0,
2139 .n_value = 0,
2140 });
2118 const sym_index = try self.allocateSymbol();
21412119 const atom = try MachO.createEmptyAtom(gpa, sym_index, @sizeOf(u64), 3);
2120 const sym = atom.getSymbolPtr(self);
2121 sym.n_type = macho.N_SECT;
21422122 self.dyld_private_atom = atom;
21432123
21442124 try self.allocateAtomCommon(atom, self.data_section_index.?);
......@@ -2163,15 +2143,11 @@ fn createStubHelperPreambleAtom(self: *MachO) !void {
21632143 .aarch64 => 2,
21642144 else => unreachable,
21652145 };
2166 const sym_index = @intCast(u32, self.locals.items.len);
2167 try self.locals.append(gpa, .{
2168 .n_strx = 0,
2169 .n_type = macho.N_SECT,
2170 .n_sect = 0,
2171 .n_desc = 0,
2172 .n_value = 0,
2173 });
2146 const sym_index = try self.allocateSymbol();
21742147 const atom = try MachO.createEmptyAtom(gpa, sym_index, size, alignment);
2148 const sym = atom.getSymbolPtr(self);
2149 sym.n_type = macho.N_SECT;
2150
21752151 const dyld_private_sym_index = self.dyld_private_atom.?.sym_index;
21762152 switch (arch) {
21772153 .x86_64 => {
......@@ -2288,15 +2264,11 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom {
22882264 .aarch64 => 2,
22892265 else => unreachable,
22902266 };
2291 const sym_index = @intCast(u32, self.locals.items.len);
2292 try self.locals.append(gpa, .{
2293 .n_strx = 0,
2294 .n_type = macho.N_SECT,
2295 .n_sect = 0,
2296 .n_desc = 0,
2297 .n_value = 0,
2298 });
2267 const sym_index = try self.allocateSymbol();
22992268 const atom = try MachO.createEmptyAtom(gpa, sym_index, stub_size, alignment);
2269 const sym = atom.getSymbolPtr(self);
2270 sym.n_type = macho.N_SECT;
2271
23002272 try atom.relocs.ensureTotalCapacity(gpa, 1);
23012273
23022274 switch (arch) {
......@@ -2352,15 +2324,11 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom {
23522324
23532325pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, target: SymbolWithLoc) !*Atom {
23542326 const gpa = self.base.allocator;
2355 const sym_index = @intCast(u32, self.locals.items.len);
2356 try self.locals.append(gpa, .{
2357 .n_strx = 0,
2358 .n_type = macho.N_SECT,
2359 .n_sect = 0,
2360 .n_desc = 0,
2361 .n_value = 0,
2362 });
2327 const sym_index = try self.allocateSymbol();
23632328 const atom = try MachO.createEmptyAtom(gpa, sym_index, @sizeOf(u64), 3);
2329 const sym = atom.getSymbolPtr(self);
2330 sym.n_type = macho.N_SECT;
2331
23642332 try atom.relocs.append(gpa, .{
23652333 .offset = 0,
23662334 .target = .{ .sym_index = stub_sym_index, .file = null },
......@@ -2376,7 +2344,7 @@ pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, target: SymbolWi
23762344 });
23772345 try atom.rebases.append(gpa, 0);
23782346
2379 const global = self.globals.get(self.getSymbolName(target)).?;
2347 const global = self.getGlobal(self.getSymbolName(target)).?;
23802348 try atom.lazy_bindings.append(gpa, .{
23812349 .target = global,
23822350 .offset = 0,
......@@ -2403,15 +2371,11 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {
24032371 .aarch64 => 3 * @sizeOf(u32),
24042372 else => unreachable, // unhandled architecture type
24052373 };
2406 const sym_index = @intCast(u32, self.locals.items.len);
2407 try self.locals.append(gpa, .{
2408 .n_strx = 0,
2409 .n_type = macho.N_SECT,
2410 .n_sect = 0,
2411 .n_desc = 0,
2412 .n_value = 0,
2413 });
2374 const sym_index = try self.allocateSymbol();
24142375 const atom = try MachO.createEmptyAtom(gpa, sym_index, stub_size, alignment);
2376 const sym = atom.getSymbolPtr(self);
2377 sym.n_type = macho.N_SECT;
2378
24152379 switch (arch) {
24162380 .x86_64 => {
24172381 // jmp
......@@ -2472,7 +2436,7 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {
24722436fn createTentativeDefAtoms(self: *MachO) !void {
24732437 const gpa = self.base.allocator;
24742438
2475 for (self.globals.values()) |global| {
2439 for (self.globals.items) |global| {
24762440 const sym = self.getSymbolPtr(global);
24772441 if (!sym.tentative()) continue;
24782442
......@@ -2516,51 +2480,44 @@ fn createTentativeDefAtoms(self: *MachO) !void {
25162480
25172481fn createMhExecuteHeaderSymbol(self: *MachO) !void {
25182482 if (self.base.options.output_mode != .Exe) return;
2519 if (self.globals.get("__mh_execute_header")) |global| {
2483 if (self.getGlobal("__mh_execute_header")) |global| {
25202484 const sym = self.getSymbol(global);
25212485 if (!sym.undf() and !(sym.pext() or sym.weakDef())) return;
25222486 }
25232487
25242488 const gpa = self.base.allocator;
2525 const n_strx = try self.strtab.insert(gpa, "__mh_execute_header");
2526 const sym_index = @intCast(u32, self.locals.items.len);
2527 try self.locals.append(gpa, .{
2528 .n_strx = n_strx,
2489 const sym_index = try self.allocateSymbol();
2490 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };
2491 const sym = self.getSymbolPtr(sym_loc);
2492 sym.* = .{
2493 .n_strx = try self.strtab.insert(gpa, "__mh_execute_header"),
25292494 .n_type = macho.N_SECT | macho.N_EXT,
25302495 .n_sect = 0,
25312496 .n_desc = macho.REFERENCED_DYNAMICALLY,
25322497 .n_value = 0,
2533 });
2534
2535 const name = try gpa.dupe(u8, "__mh_execute_header");
2536 const gop = try self.globals.getOrPut(gpa, name);
2537 defer if (gop.found_existing) gpa.free(name);
2538 gop.value_ptr.* = .{
2539 .sym_index = sym_index,
2540 .file = null,
25412498 };
2499
2500 const gop = try self.getOrPutGlobalPtr("__mh_execute_header");
2501 gop.value_ptr.* = sym_loc;
25422502}
25432503
25442504fn createDsoHandleSymbol(self: *MachO) !void {
2545 const global = self.globals.getPtr("___dso_handle") orelse return;
2546 const sym = self.getSymbolPtr(global.*);
2547 if (!sym.undf()) return;
2505 const global = self.getGlobalPtr("___dso_handle") orelse return;
2506 if (!self.getSymbol(global.*).undf()) return;
25482507
25492508 const gpa = self.base.allocator;
2550 const n_strx = try self.strtab.insert(gpa, "___dso_handle");
2551 const sym_index = @intCast(u32, self.locals.items.len);
2552 try self.locals.append(gpa, .{
2553 .n_strx = n_strx,
2509 const sym_index = try self.allocateSymbol();
2510 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };
2511 const sym = self.getSymbolPtr(sym_loc);
2512 sym.* = .{
2513 .n_strx = try self.strtab.insert(gpa, "___dso_handle"),
25542514 .n_type = macho.N_SECT | macho.N_EXT,
25552515 .n_sect = 0,
25562516 .n_desc = macho.N_WEAK_DEF,
25572517 .n_value = 0,
2558 });
2559 global.* = .{
2560 .sym_index = sym_index,
2561 .file = null,
25622518 };
2563 _ = self.unresolved.swapRemove(@intCast(u32, self.globals.getIndex("___dso_handle").?));
2519 global.* = sym_loc;
2520 _ = self.unresolved.swapRemove(self.getGlobalIndex("___dso_handle").?);
25642521}
25652522
25662523fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void {
......@@ -2568,19 +2525,14 @@ fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void {
25682525 const sym = self.getSymbol(current);
25692526 const sym_name = self.getSymbolName(current);
25702527
2571 const name = try gpa.dupe(u8, sym_name);
2572 const global_index = @intCast(u32, self.globals.values().len);
2573 const gop = try self.globals.getOrPut(gpa, name);
2574 defer if (gop.found_existing) gpa.free(name);
2575
2528 const gop = try self.getOrPutGlobalPtr(sym_name);
25762529 if (!gop.found_existing) {
25772530 gop.value_ptr.* = current;
25782531 if (sym.undf() and !sym.tentative()) {
2579 try self.unresolved.putNoClobber(gpa, global_index, false);
2532 try self.unresolved.putNoClobber(gpa, self.getGlobalIndex(sym_name).?, false);
25802533 }
25812534 return;
25822535 }
2583
25842536 const global = gop.value_ptr.*;
25852537 const global_sym = self.getSymbol(global);
25862538
......@@ -2619,7 +2571,7 @@ fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void {
26192571 }
26202572 if (sym.undf() and !sym.tentative()) return;
26212573
2622 _ = self.unresolved.swapRemove(@intCast(u32, self.globals.getIndex(name).?));
2574 _ = self.unresolved.swapRemove(self.getGlobalIndex(sym_name).?);
26232575
26242576 gop.value_ptr.* = current;
26252577}
......@@ -2664,7 +2616,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
26642616 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = object_id };
26652617 self.resolveGlobalSymbol(sym_loc) catch |err| switch (err) {
26662618 error.MultipleSymbolDefinitions => {
2667 const global = self.globals.get(sym_name).?;
2619 const global = self.getGlobal(sym_name).?;
26682620 log.err("symbol '{s}' defined multiple times", .{sym_name});
26692621 if (global.file) |file| {
26702622 log.err(" first definition in '{s}'", .{self.objects.items[file].name});
......@@ -2684,7 +2636,8 @@ fn resolveSymbolsInArchives(self: *MachO) !void {
26842636 const cpu_arch = self.base.options.target.cpu.arch;
26852637 var next_sym: usize = 0;
26862638 loop: while (next_sym < self.unresolved.count()) {
2687 const global = self.globals.values()[self.unresolved.keys()[next_sym]];
2639 const global_index = self.unresolved.keys()[next_sym];
2640 const global = self.globals.items[global_index];
26882641 const sym_name = self.getSymbolName(global);
26892642
26902643 for (self.archives.items) |archive| {
......@@ -2710,10 +2663,11 @@ fn resolveSymbolsInArchives(self: *MachO) !void {
27102663fn resolveSymbolsInDylibs(self: *MachO) !void {
27112664 if (self.dylibs.items.len == 0) return;
27122665
2666 const gpa = self.base.allocator;
27132667 var next_sym: usize = 0;
27142668 loop: while (next_sym < self.unresolved.count()) {
27152669 const global_index = self.unresolved.keys()[next_sym];
2716 const global = self.globals.values()[global_index];
2670 const global = self.globals.items[global_index];
27172671 const sym = self.getSymbolPtr(global);
27182672 const sym_name = self.getSymbolName(global);
27192673
......@@ -2722,7 +2676,7 @@ fn resolveSymbolsInDylibs(self: *MachO) !void {
27222676
27232677 const dylib_id = @intCast(u16, id);
27242678 if (!self.referenced_dylibs.contains(dylib_id)) {
2725 try self.referenced_dylibs.putNoClobber(self.base.allocator, dylib_id, {});
2679 try self.referenced_dylibs.putNoClobber(gpa, dylib_id, {});
27262680 }
27272681
27282682 const ordinal = self.referenced_dylibs.getIndex(dylib_id) orelse unreachable;
......@@ -2760,7 +2714,7 @@ fn resolveSymbolsAtLoading(self: *MachO) !void {
27602714 var next_sym: usize = 0;
27612715 while (next_sym < self.unresolved.count()) {
27622716 const global_index = self.unresolved.keys()[next_sym];
2763 const global = self.globals.values()[global_index];
2717 const global = self.globals.items[global_index];
27642718 const sym = self.getSymbolPtr(global);
27652719 const sym_name = self.getSymbolName(global);
27662720
......@@ -2800,26 +2754,27 @@ fn resolveDyldStubBinder(self: *MachO) !void {
28002754 if (self.unresolved.count() == 0) return; // no need for a stub binder if we don't have any imports
28012755
28022756 const gpa = self.base.allocator;
2803 const n_strx = try self.strtab.insert(gpa, "dyld_stub_binder");
2804 const sym_index = @intCast(u32, self.locals.items.len);
2805 try self.locals.append(gpa, .{
2806 .n_strx = n_strx,
2757 const sym_index = try self.allocateSymbol();
2758 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };
2759 const sym = self.getSymbolPtr(sym_loc);
2760 const sym_name = "dyld_stub_binder";
2761 sym.* = .{
2762 .n_strx = try self.strtab.insert(gpa, sym_name),
28072763 .n_type = macho.N_UNDF,
28082764 .n_sect = 0,
28092765 .n_desc = 0,
28102766 .n_value = 0,
2811 });
2812 const sym_name = try gpa.dupe(u8, "dyld_stub_binder");
2813 const global = SymbolWithLoc{ .sym_index = sym_index, .file = null };
2814 try self.globals.putNoClobber(gpa, sym_name, global);
2815 const sym = &self.locals.items[sym_index];
2767 };
2768 const gop = try self.getOrPutGlobalPtr(sym_name);
2769 gop.value_ptr.* = sym_loc;
2770 const global = gop.value_ptr.*;
28162771
28172772 for (self.dylibs.items) |dylib, id| {
28182773 if (!dylib.symbols.contains(sym_name)) continue;
28192774
28202775 const dylib_id = @intCast(u16, id);
28212776 if (!self.referenced_dylibs.contains(dylib_id)) {
2822 try self.referenced_dylibs.putNoClobber(self.base.allocator, dylib_id, {});
2777 try self.referenced_dylibs.putNoClobber(gpa, dylib_id, {});
28232778 }
28242779
28252780 const ordinal = self.referenced_dylibs.getIndex(dylib_id) orelse unreachable;
......@@ -3050,14 +3005,20 @@ pub fn deinit(self: *MachO) void {
30503005 self.stubs_free_list.deinit(gpa);
30513006 self.stubs_table.deinit(gpa);
30523007 self.strtab.deinit(gpa);
3008
30533009 self.locals.deinit(gpa);
3010 self.globals.deinit(gpa);
30543011 self.locals_free_list.deinit(gpa);
3012 self.globals_free_list.deinit(gpa);
30553013 self.unresolved.deinit(gpa);
30563014
3057 for (self.globals.keys()) |key| {
3058 gpa.free(key);
3015 {
3016 var it = self.resolver.keyIterator();
3017 while (it.next()) |key_ptr| {
3018 gpa.free(key_ptr.*);
3019 }
3020 self.resolver.deinit(gpa);
30593021 }
3060 self.globals.deinit(gpa);
30613022
30623023 for (self.objects.items) |*object| {
30633024 object.deinit(gpa);
......@@ -3211,6 +3172,29 @@ fn allocateSymbol(self: *MachO) !u32 {
32113172 return index;
32123173}
32133174
3175fn allocateGlobal(self: *MachO) !u32 {
3176 try self.globals.ensureUnusedCapacity(self.base.allocator, 1);
3177
3178 const index = blk: {
3179 if (self.globals_free_list.popOrNull()) |index| {
3180 log.debug(" (reusing global index {d})", .{index});
3181 break :blk index;
3182 } else {
3183 log.debug(" (allocating symbol index {d})", .{self.globals.items.len});
3184 const index = @intCast(u32, self.globals.items.len);
3185 _ = self.globals.addOneAssumeCapacity();
3186 break :blk index;
3187 }
3188 };
3189
3190 self.globals.items[index] = .{
3191 .sym_index = 0,
3192 .file = null,
3193 };
3194
3195 return index;
3196}
3197
32143198pub fn allocateGotEntry(self: *MachO, target: SymbolWithLoc) !u32 {
32153199 const gpa = self.base.allocator;
32163200 try self.got_entries.ensureUnusedCapacity(gpa, 1);
......@@ -3832,7 +3816,7 @@ pub fn updateDeclExports(
38323816
38333817 self.resolveGlobalSymbol(sym_loc) catch |err| switch (err) {
38343818 error.MultipleSymbolDefinitions => {
3835 const global = self.globals.get(exp_name).?;
3819 const global = self.getGlobal(exp_name).?;
38363820 if (sym_loc.sym_index != global.sym_index and global.file != null) {
38373821 _ = try module.failed_exports.put(module.gpa, exp, try Module.ErrorMsg.create(
38383822 gpa,
......@@ -3869,11 +3853,13 @@ pub fn deleteExport(self: *MachO, exp: Export) void {
38693853 };
38703854 self.locals_free_list.append(gpa, sym_index) catch {};
38713855
3872 if (self.globals.get(sym_name)) |global| blk: {
3873 if (global.sym_index != sym_index) break :blk;
3874 if (global.file != null) break :blk;
3875 const kv = self.globals.fetchSwapRemove(sym_name);
3876 gpa.free(kv.?.key);
3856 if (self.resolver.fetchRemove(sym_name)) |entry| {
3857 defer gpa.free(entry.key);
3858 self.globals_free_list.append(gpa, entry.value) catch {};
3859 self.globals.items[entry.value] = .{
3860 .sym_index = 0,
3861 .file = null,
3862 };
38773863 }
38783864}
38793865
......@@ -4864,32 +4850,26 @@ pub fn addAtomToSection(self: *MachO, atom: *Atom, sect_id: u8) !void {
48644850
48654851pub fn getGlobalSymbol(self: *MachO, name: []const u8) !u32 {
48664852 const gpa = self.base.allocator;
4853
48674854 const sym_name = try std.fmt.allocPrint(gpa, "_{s}", .{name});
4868 const global_index = @intCast(u32, self.globals.values().len);
4869 const gop = try self.globals.getOrPut(gpa, sym_name);
4870 defer if (gop.found_existing) gpa.free(sym_name);
4855 defer gpa.free(sym_name);
4856 const gop = try self.getOrPutGlobalPtr(sym_name);
4857 const global_index = self.getGlobalIndex(sym_name).?;
48714858
48724859 if (gop.found_existing) {
4873 // TODO audit this: can we ever reference anything from outside the Zig module?
4874 assert(gop.value_ptr.file == null);
4875 return gop.value_ptr.sym_index;
4860 return global_index;
48764861 }
48774862
4878 const sym_index = @intCast(u32, self.locals.items.len);
4879 try self.locals.append(gpa, .{
4880 .n_strx = try self.strtab.insert(gpa, sym_name),
4881 .n_type = macho.N_UNDF,
4882 .n_sect = 0,
4883 .n_desc = 0,
4884 .n_value = 0,
4885 });
4886 gop.value_ptr.* = .{
4887 .sym_index = sym_index,
4888 .file = null,
4889 };
4863 const sym_index = try self.allocateSymbol();
4864 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };
4865 gop.value_ptr.* = sym_loc;
4866
4867 const sym = self.getSymbolPtr(sym_loc);
4868 sym.n_strx = try self.strtab.insert(gpa, sym_name);
4869
48904870 try self.unresolved.putNoClobber(gpa, global_index, true);
48914871
4892 return sym_index;
4872 return global_index;
48934873}
48944874
48954875fn getSegmentAllocBase(self: MachO, indices: []const ?u8) struct { vmaddr: u64, fileoff: u64 } {
......@@ -5055,7 +5035,7 @@ fn writeDyldInfoData(self: *MachO, ncmds: *u32, lc_writer: anytype) !void {
50555035 if (self.base.options.output_mode == .Exe) {
50565036 for (&[_]SymbolWithLoc{
50575037 try self.getEntryPoint(),
5058 self.globals.get("__mh_execute_header").?,
5038 self.getGlobal("__mh_execute_header").?,
50595039 }) |global| {
50605040 const sym = self.getSymbol(global);
50615041 const sym_name = self.getSymbolName(global);
......@@ -5068,7 +5048,7 @@ fn writeDyldInfoData(self: *MachO, ncmds: *u32, lc_writer: anytype) !void {
50685048 }
50695049 } else {
50705050 assert(self.base.options.output_mode == .Lib);
5071 for (self.globals.values()) |global| {
5051 for (self.globals.items) |global| {
50725052 const sym = self.getSymbol(global);
50735053
50745054 if (sym.undf()) continue;
......@@ -5271,9 +5251,9 @@ fn writeFunctionStarts(self: *MachO, ncmds: *u32, lc_writer: anytype) !void {
52715251 // We need to sort by address first
52725252 var addresses = std.ArrayList(u64).init(gpa);
52735253 defer addresses.deinit();
5274 try addresses.ensureTotalCapacityPrecise(self.globals.count());
5254 try addresses.ensureTotalCapacityPrecise(self.globals.items.len);
52755255
5276 for (self.globals.values()) |global| {
5256 for (self.globals.items) |global| {
52775257 const sym = self.getSymbol(global);
52785258 if (sym.undf()) continue;
52795259 if (sym.n_desc == N_DESC_GCED) continue;
......@@ -5453,7 +5433,7 @@ fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx {
54535433 if (sym.n_desc == N_DESC_GCED) continue; // GCed, skip
54545434 const sym_loc = SymbolWithLoc{ .sym_index = @intCast(u32, sym_id), .file = null };
54555435 if (self.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip
5456 if (self.globals.contains(self.getSymbolName(sym_loc))) continue; // global symbol is either an export or import, skip
5436 if (self.getGlobal(self.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip
54575437 try locals.append(sym);
54585438 }
54595439
......@@ -5463,7 +5443,7 @@ fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx {
54635443 if (sym.n_desc == N_DESC_GCED) continue; // GCed, skip
54645444 const sym_loc = SymbolWithLoc{ .sym_index = @intCast(u32, sym_id), .file = @intCast(u32, object_id) };
54655445 if (self.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip
5466 if (self.globals.contains(self.getSymbolName(sym_loc))) continue; // global symbol is either an export or import, skip
5446 if (self.getGlobal(self.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip
54675447 var out_sym = sym;
54685448 out_sym.n_strx = try self.strtab.insert(gpa, self.getSymbolName(sym_loc));
54695449 try locals.append(out_sym);
......@@ -5477,7 +5457,7 @@ fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx {
54775457 var exports = std.ArrayList(macho.nlist_64).init(gpa);
54785458 defer exports.deinit();
54795459
5480 for (self.globals.values()) |global| {
5460 for (self.globals.items) |global| {
54815461 const sym = self.getSymbol(global);
54825462 if (sym.undf()) continue; // import, skip
54835463 if (sym.n_desc == N_DESC_GCED) continue; // GCed, skip
......@@ -5491,7 +5471,7 @@ fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx {
54915471
54925472 var imports_table = std.AutoHashMap(SymbolWithLoc, u32).init(gpa);
54935473
5494 for (self.globals.values()) |global| {
5474 for (self.globals.items) |global| {
54955475 const sym = self.getSymbol(global);
54965476 if (sym.n_strx == 0) continue; // no name, skip
54975477 if (!sym.undf()) continue; // not an import, skip
......@@ -5798,6 +5778,49 @@ pub fn getSymbolName(self: *MachO, sym_with_loc: SymbolWithLoc) []const u8 {
57985778 }
57995779}
58005780
5781/// Returns pointer to the global entry for `name` if one exists.
5782pub fn getGlobalPtr(self: *MachO, name: []const u8) ?*SymbolWithLoc {
5783 const global_index = self.resolver.get(name) orelse return null;
5784 return &self.globals.items[global_index];
5785}
5786
5787/// Returns the global entry for `name` if one exists.
5788pub fn getGlobal(self: *const MachO, name: []const u8) ?SymbolWithLoc {
5789 const global_index = self.resolver.get(name) orelse return null;
5790 return self.globals.items[global_index];
5791}
5792
5793/// Returns the index of the global entry for `name` if one exists.
5794pub fn getGlobalIndex(self: *const MachO, name: []const u8) ?u32 {
5795 return self.resolver.get(name);
5796}
5797
5798/// Returns global entry at `index`.
5799pub fn getGlobalByIndex(self: *const MachO, index: u32) SymbolWithLoc {
5800 assert(index < self.globals.items.len);
5801 return self.globals.items[index];
5802}
5803
5804const GetOrPutGlobalPtrResult = struct {
5805 found_existing: bool,
5806 value_ptr: *SymbolWithLoc,
5807};
5808
5809/// Return pointer to the global entry for `name` if one exists.
5810/// Puts a new global entry for `name` if one doesn't exist, and
5811/// returns a pointer to it.
5812pub fn getOrPutGlobalPtr(self: *MachO, name: []const u8) !GetOrPutGlobalPtrResult {
5813 if (self.getGlobalPtr(name)) |ptr| {
5814 return GetOrPutGlobalPtrResult{ .found_existing = true, .value_ptr = ptr };
5815 }
5816 const gpa = self.base.allocator;
5817 const global_index = try self.allocateGlobal();
5818 const global_name = try gpa.dupe(u8, name);
5819 _ = try self.resolver.put(gpa, global_name, global_index);
5820 const ptr = &self.globals.items[global_index];
5821 return GetOrPutGlobalPtrResult{ .found_existing = false, .value_ptr = ptr };
5822}
5823
58015824/// Returns atom if there is an atom referenced by the symbol described by `sym_with_loc` descriptor.
58025825/// Returns null on failure.
58035826pub fn getAtomForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?*Atom {
......@@ -5834,7 +5857,7 @@ pub fn getTlvPtrAtomForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?*Atom
58345857/// Asserts output mode is executable.
58355858pub fn getEntryPoint(self: MachO) error{MissingMainEntrypoint}!SymbolWithLoc {
58365859 const entry_name = self.base.options.entry orelse "_main";
5837 const global = self.globals.get(entry_name) orelse {
5860 const global = self.getGlobal(entry_name) orelse {
58385861 log.err("entrypoint '{s}' not found", .{entry_name});
58395862 return error.MissingMainEntrypoint;
58405863 };
......@@ -6342,9 +6365,9 @@ fn logSymtab(self: *MachO) void {
63426365 }
63436366
63446367 log.debug("globals table:", .{});
6345 for (self.globals.keys()) |name, id| {
6346 const value = self.globals.values()[id];
6347 log.debug(" {s} => %{d} in object({?d})", .{ name, value.sym_index, value.file });
6368 for (self.globals.items) |global| {
6369 const name = self.getSymbolName(global);
6370 log.debug(" {s} => %{d} in object({?d})", .{ name, global.sym_index, global.file });
63486371 }
63496372
63506373 log.debug("GOT entries:", .{});
src/link/MachO/Atom.zig+3-3
......@@ -272,7 +272,7 @@ pub fn parseRelocs(self: *Atom, relocs: []align(1) const macho.relocation_info,
272272 subtractor = sym_loc;
273273 } else {
274274 const sym_name = context.macho_file.getSymbolName(sym_loc);
275 subtractor = context.macho_file.globals.get(sym_name).?;
275 subtractor = context.macho_file.getGlobal(sym_name).?;
276276 }
277277 // Verify that *_SUBTRACTOR is followed by *_UNSIGNED.
278278 if (relocs.len <= i + 1) {
......@@ -339,7 +339,7 @@ pub fn parseRelocs(self: *Atom, relocs: []align(1) const macho.relocation_info,
339339 break :target sym_loc;
340340 } else {
341341 const sym_name = context.macho_file.getSymbolName(sym_loc);
342 break :target context.macho_file.globals.get(sym_name).?;
342 break :target context.macho_file.getGlobal(sym_name).?;
343343 }
344344 };
345345 const offset = @intCast(u32, rel.r_address - context.base_offset);
......@@ -579,7 +579,7 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void {
579579 // If there is no atom for target, we still need to check for special, atom-less
580580 // symbols such as `___dso_handle`.
581581 const target_name = macho_file.getSymbolName(rel.target);
582 assert(macho_file.globals.contains(target_name));
582 assert(macho_file.getGlobal(target_name) != null);
583583 const atomless_sym = macho_file.getSymbol(rel.target);
584584 log.debug(" | atomless target '{s}'", .{target_name});
585585 break :blk atomless_sym.n_value;
src/link/MachO/DebugSymbols.zig+2-2
......@@ -480,7 +480,7 @@ fn writeSymtab(self: *DebugSymbols, lc: *macho.symtab_command) !void {
480480 if (sym.n_desc == MachO.N_DESC_GCED) continue; // GCed, skip
481481 const sym_loc = MachO.SymbolWithLoc{ .sym_index = @intCast(u32, sym_id), .file = null };
482482 if (self.base.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip
483 if (self.base.globals.contains(self.base.getSymbolName(sym_loc))) continue; // global symbol is either an export or import, skip
483 if (self.base.getGlobal(self.base.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip
484484 var out_sym = sym;
485485 out_sym.n_strx = try self.strtab.insert(gpa, self.base.getSymbolName(sym_loc));
486486 try locals.append(out_sym);
......@@ -489,7 +489,7 @@ fn writeSymtab(self: *DebugSymbols, lc: *macho.symtab_command) !void {
489489 var exports = std.ArrayList(macho.nlist_64).init(gpa);
490490 defer exports.deinit();
491491
492 for (self.base.globals.values()) |global| {
492 for (self.base.globals.items) |global| {
493493 const sym = self.base.getSymbol(global);
494494 if (sym.undf()) continue; // import, skip
495495 if (sym.n_desc == MachO.N_DESC_GCED) continue; // GCed, skip
src/link/MachO/dead_strip.zig+2-2
......@@ -62,7 +62,7 @@ fn collectRoots(roots: *std.AutoHashMap(*Atom, void), macho_file: *MachO) !void
6262 else => |other| {
6363 assert(other == .Lib);
6464 // Add exports as GC roots
65 for (macho_file.globals.values()) |global| {
65 for (macho_file.globals.items) |global| {
6666 const sym = macho_file.getSymbol(global);
6767 if (!sym.sect()) continue;
6868 const atom = macho_file.getAtomForSymbol(global) orelse {
......@@ -77,7 +77,7 @@ fn collectRoots(roots: *std.AutoHashMap(*Atom, void), macho_file: *MachO) !void
7777 }
7878
7979 // TODO just a temp until we learn how to parse unwind records
80 if (macho_file.globals.get("___gxx_personality_v0")) |global| {
80 if (macho_file.getGlobal("___gxx_personality_v0")) |global| {
8181 if (macho_file.getAtomForSymbol(global)) |atom| {
8282 _ = try roots.getOrPut(atom);
8383 log.debug("adding root", .{});