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) {...@@ -139,21 +139,10 @@ const MCValue = union(enum) {
139 /// If the type is a pointer, it means the pointer address is at139 /// If the type is a pointer, it means the pointer address is at
140 /// this memory location.140 /// this memory location.
141 memory: u64,141 memory: u64,
142 /// The value is in memory referenced indirectly via a GOT entry142 /// The value is in memory but requires a linker relocation fixup:
143 /// index.143 /// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc)
144 ///144 /// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc)
145 /// If the type is a pointer, it means the pointer is referenced145 linker_load: struct { @"type": enum { got, direct }, sym_index: u32 },
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,
157 /// The value is one of the stack variables.146 /// The value is one of the stack variables.
158 ///147 ///
159 /// If the type is a pointer, it means the pointer address is in148 /// 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...@@ -2959,8 +2948,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2959 .memory,2948 .memory,
2960 .stack_offset,2949 .stack_offset,
2961 .stack_argument_offset,2950 .stack_argument_offset,
2962 .got_load,2951 .linker_load,
2963 .direct_load,
2964 => {2952 => {
2965 const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr);2953 const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr);
2966 try self.load(dst_mcv, .{ .register = addr_reg }, ptr_ty);2954 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...@@ -3197,8 +3185,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
3197 .memory,3185 .memory,
3198 .stack_offset,3186 .stack_offset,
3199 .stack_argument_offset,3187 .stack_argument_offset,
3200 .got_load,3188 .linker_load,
3201 .direct_load,
3202 => {3189 => {
3203 const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr);3190 const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr);
3204 try self.store(.{ .register = addr_reg }, value, ptr_ty, value_ty);3191 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....@@ -3493,7 +3480,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
3493 const func = func_payload.data;3480 const func = func_payload.data;
3494 const fn_owner_decl = mod.declPtr(func.owner_decl);3481 const fn_owner_decl = mod.declPtr(func.owner_decl);
3495 try self.genSetReg(Type.initTag(.u64), .x30, .{3482 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 },
3497 });3487 });
3498 // blr x303488 // blr x30
3499 _ = try self.addInst(.{3489 _ = try self.addInst(.{
...@@ -4427,8 +4417,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -4427,8 +4417,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
4427 .register = cond_reg,4417 .register = cond_reg,
4428 });4418 });
4429 },4419 },
4430 .got_load,4420 .linker_load,
4431 .direct_load,
4432 .memory,4421 .memory,
4433 .stack_argument_offset,4422 .stack_argument_offset,
4434 .stack_offset,4423 .stack_offset,
...@@ -4479,13 +4468,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -4479,13 +4468,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
4479 });4468 });
4480 },4469 },
4481 .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = addr }),4470 .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = addr }),
4482 .got_load,4471 .linker_load => |load_struct| {
4483 .direct_load,4472 const tag: Mir.Inst.Tag = switch (load_struct.@"type") {
4484 => |sym_index| {4473 .got => .load_memory_ptr_got,
4485 const tag: Mir.Inst.Tag = switch (mcv) {4474 .direct => .load_memory_ptr_direct,
4486 .got_load => .load_memory_ptr_got,
4487 .direct_load => .load_memory_ptr_direct,
4488 else => unreachable,
4489 };4475 };
4490 const mod = self.bin_file.options.module.?;4476 const mod = self.bin_file.options.module.?;
4491 _ = try self.addInst(.{4477 _ = try self.addInst(.{
...@@ -4494,7 +4480,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -4494,7 +4480,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
4494 .payload = try self.addExtra(Mir.LoadMemoryPie{4480 .payload = try self.addExtra(Mir.LoadMemoryPie{
4495 .register = @enumToInt(src_reg),4481 .register = @enumToInt(src_reg),
4496 .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.sym_index,4482 .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,
4498 }),4484 }),
4499 },4485 },
4500 });4486 });
...@@ -4594,13 +4580,10 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -4594,13 +4580,10 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
4594 });4580 });
4595 },4581 },
4596 .register_with_overflow => unreachable, // doesn't fit into a register4582 .register_with_overflow => unreachable, // doesn't fit into a register
4597 .got_load,4583 .linker_load => |load_struct| {
4598 .direct_load,4584 const tag: Mir.Inst.Tag = switch (load_struct.@"type") {
4599 => |sym_index| {4585 .got => .load_memory_got,
4600 const tag: Mir.Inst.Tag = switch (mcv) {4586 .direct => .load_memory_direct,
4601 .got_load => .load_memory_got,
4602 .direct_load => .load_memory_direct,
4603 else => unreachable,
4604 };4587 };
4605 const mod = self.bin_file.options.module.?;4588 const mod = self.bin_file.options.module.?;
4606 _ = try self.addInst(.{4589 _ = try self.addInst(.{
...@@ -4609,7 +4592,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -4609,7 +4592,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
4609 .payload = try self.addExtra(Mir.LoadMemoryPie{4592 .payload = try self.addExtra(Mir.LoadMemoryPie{
4610 .register = @enumToInt(reg),4593 .register = @enumToInt(reg),
4611 .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.sym_index,4594 .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,
4613 }),4596 }),
4614 },4597 },
4615 });4598 });
...@@ -4741,8 +4724,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -4741,8 +4724,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
4741 .register_with_overflow => {4724 .register_with_overflow => {
4742 return self.fail("TODO implement genSetStackArgument {}", .{mcv});4725 return self.fail("TODO implement genSetStackArgument {}", .{mcv});
4743 },4726 },
4744 .got_load,4727 .linker_load,
4745 .direct_load,
4746 .memory,4728 .memory,
4747 .stack_argument_offset,4729 .stack_argument_offset,
4748 .stack_offset,4730 .stack_offset,
...@@ -4785,13 +4767,10 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -4785,13 +4767,10 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
4785 });4767 });
4786 },4768 },
4787 .memory => |addr| try self.genSetReg(ptr_ty, src_reg, .{ .immediate = @intCast(u32, addr) }),4769 .memory => |addr| try self.genSetReg(ptr_ty, src_reg, .{ .immediate = @intCast(u32, addr) }),
4788 .got_load,4770 .linker_load => |load_struct| {
4789 .direct_load,4771 const tag: Mir.Inst.Tag = switch (load_struct.@"type") {
4790 => |sym_index| {4772 .got => .load_memory_ptr_got,
4791 const tag: Mir.Inst.Tag = switch (mcv) {4773 .direct => .load_memory_ptr_direct,
4792 .got_load => .load_memory_ptr_got,
4793 .direct_load => .load_memory_ptr_direct,
4794 else => unreachable,
4795 };4774 };
4796 const mod = self.bin_file.options.module.?;4775 const mod = self.bin_file.options.module.?;
4797 _ = try self.addInst(.{4776 _ = try self.addInst(.{
...@@ -4800,7 +4779,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -4800,7 +4779,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
4800 .payload = try self.addExtra(Mir.LoadMemoryPie{4779 .payload = try self.addExtra(Mir.LoadMemoryPie{
4801 .register = @enumToInt(src_reg),4780 .register = @enumToInt(src_reg),
4802 .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.sym_index,4781 .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,
4804 }),4783 }),
4805 },4784 },
4806 });4785 });
...@@ -5107,7 +5086,10 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne...@@ -5107,7 +5086,10 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
5107 // Because MachO is PIE-always-on, we defer memory address resolution until5086 // Because MachO is PIE-always-on, we defer memory address resolution until
5108 // the linker has enough info to perform relocations.5087 // the linker has enough info to perform relocations.
5109 assert(decl.link.macho.sym_index != 0);5088 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 } };
5111 } else if (self.bin_file.cast(link.File.Coff)) |_| {5093 } else if (self.bin_file.cast(link.File.Coff)) |_| {
5112 return self.fail("TODO codegen COFF const Decl pointer", .{});5094 return self.fail("TODO codegen COFF const Decl pointer", .{});
5113 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {5095 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
...@@ -5129,7 +5111,10 @@ fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue {...@@ -5129,7 +5111,10 @@ fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue {
5129 const vaddr = elf_file.local_symbols.items[local_sym_index].st_value;5111 const vaddr = elf_file.local_symbols.items[local_sym_index].st_value;
5130 return MCValue{ .memory = vaddr };5112 return MCValue{ .memory = vaddr };
5131 } else if (self.bin_file.cast(link.File.MachO)) |_| {5113 } 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 } };
5133 } else if (self.bin_file.cast(link.File.Coff)) |_| {5118 } else if (self.bin_file.cast(link.File.Coff)) |_| {
5134 return self.fail("TODO lower unnamed const in COFF", .{});5119 return self.fail("TODO lower unnamed const in COFF", .{});
5135 } else if (self.bin_file.cast(link.File.Plan9)) |_| {5120 } 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 {...@@ -681,12 +681,10 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void {
681 };681 };
682 // Add relocation to the decl.682 // Add relocation to the decl.
683 const atom = macho_file.atom_by_index_table.get(relocation.atom_index).?;683 const atom = macho_file.atom_by_index_table.get(relocation.atom_index).?;
684 const target = macho_file.getGlobalByIndex(relocation.sym_index);
684 try atom.relocs.append(emit.bin_file.allocator, .{685 try atom.relocs.append(emit.bin_file.allocator, .{
685 .offset = offset,686 .offset = offset,
686 .target = .{687 .target = target,
687 .sym_index = relocation.sym_index,
688 .file = null,
689 },
690 .addend = 0,688 .addend = 0,
691 .subtractor = null,689 .subtractor = null,
692 .pcrel = true,690 .pcrel = true,
src/arch/x86_64/CodeGen.zig+67-141
...@@ -128,15 +128,11 @@ pub const MCValue = union(enum) {...@@ -128,15 +128,11 @@ pub const MCValue = union(enum) {
128 /// The value is in memory at a hard-coded address.128 /// The value is in memory at a hard-coded address.
129 /// If the type is a pointer, it means the pointer address is at this memory location.129 /// If the type is a pointer, it means the pointer address is at this memory location.
130 memory: u64,130 memory: u64,
131 /// The value is in memory referenced indirectly via a GOT entry index.131 /// The value is in memory but requires a linker relocation fixup:
132 /// If the type is a pointer, it means the pointer is referenced indirectly via GOT.132 /// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc)
133 /// When lowered, linker will emit a relocation of type X86_64_RELOC_GOT.133 /// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc)
134 got_load: u32,134 /// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc)
135 imports_load: u32,135 linker_load: struct { @"type": enum { got, direct, import }, sym_index: 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,
140 /// The value is one of the stack variables.136 /// The value is one of the stack variables.
141 /// If the type is a pointer, it means the pointer address is in the stack at this offset.137 /// If the type is a pointer, it means the pointer address is in the stack at this offset.
142 stack_offset: i32,138 stack_offset: i32,
...@@ -150,9 +146,7 @@ pub const MCValue = union(enum) {...@@ -150,9 +146,7 @@ pub const MCValue = union(enum) {
150 .memory,146 .memory,
151 .stack_offset,147 .stack_offset,
152 .ptr_stack_offset,148 .ptr_stack_offset,
153 .direct_load,149 .linker_load,
154 .got_load,
155 .imports_load,
156 => true,150 => true,
157 else => false,151 else => false,
158 };152 };
...@@ -165,26 +159,6 @@ pub const MCValue = union(enum) {...@@ -165,26 +159,6 @@ pub const MCValue = union(enum) {
165 };159 };
166 }160 }
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
188 fn isRegister(mcv: MCValue) bool {162 fn isRegister(mcv: MCValue) bool {
189 return switch (mcv) {163 return switch (mcv) {
190 .register => true,164 .register => true,
...@@ -2307,11 +2281,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2307,11 +2281,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
2307 .data = .{ .imm = @bitCast(u32, -off) },2281 .data = .{ .imm = @bitCast(u32, -off) },
2308 });2282 });
2309 },2283 },
2310 .memory,2284 .memory, .linker_load => {
2311 .got_load,
2312 .direct_load,
2313 .imports_load,
2314 => {
2315 try self.loadMemPtrIntoRegister(addr_reg, Type.usize, array);2285 try self.loadMemPtrIntoRegister(addr_reg, Type.usize, array);
2316 },2286 },
2317 else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),2287 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...@@ -2652,11 +2622,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2652 else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}),2622 else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}),
2653 }2623 }
2654 },2624 },
2655 .memory,2625 .memory, .linker_load => {
2656 .got_load,
2657 .direct_load,
2658 .imports_load,
2659 => {
2660 const reg = try self.copyToTmpRegister(ptr_ty, ptr);2626 const reg = try self.copyToTmpRegister(ptr_ty, ptr);
2661 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);2627 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);
2662 },2628 },
...@@ -2691,10 +2657,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -2691,10 +2657,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
26912657
2692fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue) InnerError!void {2658fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue) InnerError!void {
2693 switch (ptr) {2659 switch (ptr) {
2694 .got_load,2660 .linker_load => |load_struct| {
2695 .direct_load,
2696 .imports_load,
2697 => |sym_index| {
2698 const abi_size = @intCast(u32, ptr_ty.abiSize(self.target.*));2661 const abi_size = @intCast(u32, ptr_ty.abiSize(self.target.*));
2699 const mod = self.bin_file.options.module.?;2662 const mod = self.bin_file.options.module.?;
2700 const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl);2663 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...@@ -2702,11 +2665,10 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue
2702 fn_owner_decl.link.macho.sym_index2665 fn_owner_decl.link.macho.sym_index
2703 else2666 else
2704 fn_owner_decl.link.coff.sym_index;2667 fn_owner_decl.link.coff.sym_index;
2705 const flags: u2 = switch (ptr) {2668 const flags: u2 = switch (load_struct.@"type") {
2706 .got_load => 0b00,2669 .got => 0b00,
2707 .direct_load => 0b01,2670 .direct => 0b01,
2708 .imports_load => 0b10,2671 .import => 0b10,
2709 else => unreachable,
2710 };2672 };
2711 _ = try self.addInst(.{2673 _ = try self.addInst(.{
2712 .tag = .lea_pic,2674 .tag = .lea_pic,
...@@ -2717,7 +2679,7 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue...@@ -2717,7 +2679,7 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue
2717 .data = .{2679 .data = .{
2718 .relocation = .{2680 .relocation = .{
2719 .atom_index = atom_index,2681 .atom_index = atom_index,
2720 .sym_index = sym_index,2682 .sym_index = load_struct.sym_index,
2721 },2683 },
2722 },2684 },
2723 });2685 });
...@@ -2801,9 +2763,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2801,9 +2763,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2801 .register => |src_reg| {2763 .register => |src_reg| {
2802 try self.genInlineMemcpyRegisterRegister(value_ty, reg, src_reg, 0);2764 try self.genInlineMemcpyRegisterRegister(value_ty, reg, src_reg, 0);
2803 },2765 },
2804 .got_load,2766 .linker_load,
2805 .direct_load,
2806 .imports_load,
2807 .memory,2767 .memory,
2808 .stack_offset,2768 .stack_offset,
2809 => {2769 => {
...@@ -2822,11 +2782,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2822,11 +2782,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2822 },2782 },
2823 }2783 }
2824 },2784 },
2825 .got_load,2785 .linker_load, .memory => {
2826 .direct_load,
2827 .imports_load,
2828 .memory,
2829 => {
2830 const value_lock: ?RegisterLock = switch (value) {2786 const value_lock: ?RegisterLock = switch (value) {
2831 .register => |reg| self.register_manager.lockReg(reg),2787 .register => |reg| self.register_manager.lockReg(reg),
2832 else => null,2788 else => null,
...@@ -2894,11 +2850,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2894,11 +2850,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2894 .register => {2850 .register => {
2895 return self.store(new_ptr, value, ptr_ty, value_ty);2851 return self.store(new_ptr, value, ptr_ty, value_ty);
2896 },2852 },
2897 .got_load,2853 .linker_load, .memory => {
2898 .direct_load,
2899 .imports_load,
2900 .memory,
2901 => {
2902 if (abi_size <= 8) {2854 if (abi_size <= 8) {
2903 const tmp_reg = try self.register_manager.allocReg(null, gp);2855 const tmp_reg = try self.register_manager.allocReg(null, gp);
2904 const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);2856 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...@@ -3606,9 +3558,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu
3606 });3558 });
3607 },3559 },
3608 .memory,3560 .memory,
3609 .got_load,3561 .linker_load,
3610 .direct_load,
3611 .imports_load,
3612 .eflags,3562 .eflags,
3613 => {3563 => {
3614 assert(abi_size <= 8);3564 assert(abi_size <= 8);
...@@ -3694,10 +3644,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu...@@ -3694,10 +3644,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu
3694 => {3644 => {
3695 return self.fail("TODO implement x86 ADD/SUB/CMP source memory", .{});3645 return self.fail("TODO implement x86 ADD/SUB/CMP source memory", .{});
3696 },3646 },
3697 .got_load,3647 .linker_load => {
3698 .direct_load,
3699 .imports_load,
3700 => {
3701 return self.fail("TODO implement x86 ADD/SUB/CMP source symbol at index in linker", .{});3648 return self.fail("TODO implement x86 ADD/SUB/CMP source symbol at index in linker", .{});
3702 },3649 },
3703 .eflags => {3650 .eflags => {
...@@ -3708,10 +3655,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu...@@ -3708,10 +3655,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu
3708 .memory => {3655 .memory => {
3709 return self.fail("TODO implement x86 ADD/SUB/CMP destination memory", .{});3656 return self.fail("TODO implement x86 ADD/SUB/CMP destination memory", .{});
3710 },3657 },
3711 .got_load,3658 .linker_load => {
3712 .direct_load,
3713 .imports_load,
3714 => {
3715 return self.fail("TODO implement x86 ADD/SUB/CMP destination symbol at index", .{});3659 return self.fail("TODO implement x86 ADD/SUB/CMP destination symbol at index", .{});
3716 },3660 },
3717 }3661 }
...@@ -3779,10 +3723,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M...@@ -3779,10 +3723,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
3779 .memory => {3723 .memory => {
3780 return self.fail("TODO implement x86 multiply source memory", .{});3724 return self.fail("TODO implement x86 multiply source memory", .{});
3781 },3725 },
3782 .got_load,3726 .linker_load => {
3783 .direct_load,
3784 .imports_load,
3785 => {
3786 return self.fail("TODO implement x86 multiply source symbol at index in linker", .{});3727 return self.fail("TODO implement x86 multiply source symbol at index in linker", .{});
3787 },3728 },
3788 .eflags => {3729 .eflags => {
...@@ -3826,10 +3767,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M...@@ -3826,10 +3767,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
3826 .memory, .stack_offset => {3767 .memory, .stack_offset => {
3827 return self.fail("TODO implement x86 multiply source memory", .{});3768 return self.fail("TODO implement x86 multiply source memory", .{});
3828 },3769 },
3829 .got_load,3770 .linker_load => {
3830 .direct_load,
3831 .imports_load,
3832 => {
3833 return self.fail("TODO implement x86 multiply source symbol at index in linker", .{});3771 return self.fail("TODO implement x86 multiply source symbol at index in linker", .{});
3834 },3772 },
3835 .eflags => {3773 .eflags => {
...@@ -3840,10 +3778,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M...@@ -3840,10 +3778,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
3840 .memory => {3778 .memory => {
3841 return self.fail("TODO implement x86 multiply destination memory", .{});3779 return self.fail("TODO implement x86 multiply destination memory", .{});
3842 },3780 },
3843 .got_load,3781 .linker_load => {
3844 .direct_load,
3845 .imports_load,
3846 => {
3847 return self.fail("TODO implement x86 multiply destination symbol at index in linker", .{});3782 return self.fail("TODO implement x86 multiply destination symbol at index in linker", .{});
3848 },3783 },
3849 }3784 }
...@@ -4006,9 +3941,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions....@@ -4006,9 +3941,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
4006 .unreach => unreachable,3941 .unreach => unreachable,
4007 .dead => unreachable,3942 .dead => unreachable,
4008 .memory => unreachable,3943 .memory => unreachable,
4009 .got_load => unreachable,3944 .linker_load => unreachable,
4010 .direct_load => unreachable,
4011 .imports_load => unreachable,
4012 .eflags => unreachable,3945 .eflags => unreachable,
4013 .register_overflow => unreachable,3946 .register_overflow => unreachable,
4014 }3947 }
...@@ -4066,7 +3999,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions....@@ -4066,7 +3999,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
4066 const func = func_payload.data;3999 const func = func_payload.data;
4067 const fn_owner_decl = mod.declPtr(func.owner_decl);4000 const fn_owner_decl = mod.declPtr(func.owner_decl);
4068 try self.genSetReg(Type.initTag(.usize), .rax, .{4001 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 },
4070 });4006 });
4071 _ = try self.addInst(.{4007 _ = try self.addInst(.{
4072 .tag = .call,4008 .tag = .call,
...@@ -4087,7 +4023,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions....@@ -4087,7 +4023,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
4087 }4023 }
4088 const sym_index = try coff_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));4024 const sym_index = try coff_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));
4089 try self.genSetReg(Type.initTag(.usize), .rax, .{4025 try self.genSetReg(Type.initTag(.usize), .rax, .{
4090 .imports_load = sym_index,4026 .linker_load = .{
4027 .@"type" = .import,
4028 .sym_index = sym_index,
4029 },
4091 });4030 });
4092 _ = try self.addInst(.{4031 _ = try self.addInst(.{
4093 .tag = .call,4032 .tag = .call,
...@@ -4119,7 +4058,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions....@@ -4119,7 +4058,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
4119 const func = func_payload.data;4058 const func = func_payload.data;
4120 const fn_owner_decl = mod.declPtr(func.owner_decl);4059 const fn_owner_decl = mod.declPtr(func.owner_decl);
4121 const sym_index = fn_owner_decl.link.macho.sym_index;4060 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 });
4123 // callq *%rax4067 // callq *%rax
4124 _ = try self.addInst(.{4068 _ = try self.addInst(.{
4125 .tag = .call,4069 .tag = .call,
...@@ -4505,11 +4449,7 @@ fn genVarDbgInfo(...@@ -4505,11 +4449,7 @@ fn genVarDbgInfo(
4505 leb128.writeILEB128(dbg_info.writer(), -off) catch unreachable;4449 leb128.writeILEB128(dbg_info.writer(), -off) catch unreachable;
4506 dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);4450 dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
4507 },4451 },
4508 .memory,4452 .memory, .linker_load => {
4509 .got_load,
4510 .direct_load,
4511 .imports_load,
4512 => {
4513 const ptr_width = @intCast(u8, @divExact(self.target.cpu.arch.ptrBitWidth(), 8));4453 const ptr_width = @intCast(u8, @divExact(self.target.cpu.arch.ptrBitWidth(), 8));
4514 const is_ptr = switch (tag) {4454 const is_ptr = switch (tag) {
4515 .dbg_var_ptr => true,4455 .dbg_var_ptr => true,
...@@ -4540,10 +4480,11 @@ fn genVarDbgInfo(...@@ -4540,10 +4480,11 @@ fn genVarDbgInfo(
4540 try dbg_info.append(DW.OP.deref);4480 try dbg_info.append(DW.OP.deref);
4541 }4481 }
4542 switch (mcv) {4482 switch (mcv) {
4543 .got_load,4483 .linker_load => |load_struct| try dw.addExprlocReloc(
4544 .direct_load,4484 load_struct.sym_index,
4545 .imports_load,4485 offset,
4546 => |index| try dw.addExprlocReloc(index, offset, is_ptr),4486 is_ptr,
4487 ),
4547 else => {},4488 else => {},
4548 }4489 }
4549 },4490 },
...@@ -5587,11 +5528,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE...@@ -5587,11 +5528,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
5587 else => return self.fail("TODO implement inputs on stack for {} with abi size > 8", .{mcv}),5528 else => return self.fail("TODO implement inputs on stack for {} with abi size > 8", .{mcv}),
5588 }5529 }
5589 },5530 },
5590 .memory,5531 .memory, .linker_load => {
5591 .direct_load,
5592 .got_load,
5593 .imports_load,
5594 => {
5595 if (abi_size <= 8) {5532 if (abi_size <= 8) {
5596 const reg = try self.copyToTmpRegister(ty, mcv);5533 const reg = try self.copyToTmpRegister(ty, mcv);
5597 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });5534 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...@@ -5835,11 +5772,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
5835 },5772 },
5836 }5773 }
5837 },5774 },
5838 .memory,5775 .memory, .linker_load => {
5839 .got_load,
5840 .direct_load,
5841 .imports_load,
5842 => {
5843 if (abi_size <= 8) {5776 if (abi_size <= 8) {
5844 const reg = try self.copyToTmpRegister(ty, mcv);5777 const reg = try self.copyToTmpRegister(ty, mcv);
5845 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }, opts);5778 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }, opts);
...@@ -5959,11 +5892,7 @@ fn genInlineMemcpy(...@@ -5959,11 +5892,7 @@ fn genInlineMemcpy(
5959 const tmp_reg = regs[4].to8();5892 const tmp_reg = regs[4].to8();
59605893
5961 switch (dst_ptr) {5894 switch (dst_ptr) {
5962 .memory,5895 .memory, .linker_load => {
5963 .got_load,
5964 .direct_load,
5965 .imports_load,
5966 => {
5967 try self.loadMemPtrIntoRegister(dst_addr_reg, Type.usize, dst_ptr);5896 try self.loadMemPtrIntoRegister(dst_addr_reg, Type.usize, dst_ptr);
5968 },5897 },
5969 .ptr_stack_offset, .stack_offset => |off| {5898 .ptr_stack_offset, .stack_offset => |off| {
...@@ -5992,11 +5921,7 @@ fn genInlineMemcpy(...@@ -5992,11 +5921,7 @@ fn genInlineMemcpy(
5992 }5921 }
59935922
5994 switch (src_ptr) {5923 switch (src_ptr) {
5995 .memory,5924 .memory, .linker_load => {
5996 .got_load,
5997 .direct_load,
5998 .imports_load,
5999 => {
6000 try self.loadMemPtrIntoRegister(src_addr_reg, Type.usize, src_ptr);5925 try self.loadMemPtrIntoRegister(src_addr_reg, Type.usize, src_ptr);
6001 },5926 },
6002 .ptr_stack_offset, .stack_offset => |off| {5927 .ptr_stack_offset, .stack_offset => |off| {
...@@ -6120,11 +6045,7 @@ fn genInlineMemset(...@@ -6120,11 +6045,7 @@ fn genInlineMemset(
6120 const index_reg = regs[1].to64();6045 const index_reg = regs[1].to64();
61216046
6122 switch (dst_ptr) {6047 switch (dst_ptr) {
6123 .memory,6048 .memory, .linker_load => {
6124 .got_load,
6125 .direct_load,
6126 .imports_load,
6127 => {
6128 try self.loadMemPtrIntoRegister(addr_reg, Type.usize, dst_ptr);6049 try self.loadMemPtrIntoRegister(addr_reg, Type.usize, dst_ptr);
6129 },6050 },
6130 .ptr_stack_offset, .stack_offset => |off| {6051 .ptr_stack_offset, .stack_offset => |off| {
...@@ -6356,10 +6277,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -6356,10 +6277,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
6356 .data = undefined,6277 .data = undefined,
6357 });6278 });
6358 },6279 },
6359 .direct_load,6280 .linker_load => {
6360 .got_load,
6361 .imports_load,
6362 => {
6363 switch (ty.zigTypeTag()) {6281 switch (ty.zigTypeTag()) {
6364 .Float => {6282 .Float => {
6365 const base_reg = try self.register_manager.allocReg(null, gp);6283 const base_reg = try self.register_manager.allocReg(null, gp);
...@@ -6753,11 +6671,7 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {...@@ -6753,11 +6671,7 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
6753 // TODO Is this the only condition for pointer dereference for memcpy?6671 // TODO Is this the only condition for pointer dereference for memcpy?
6754 const src: MCValue = blk: {6672 const src: MCValue = blk: {
6755 switch (src_ptr) {6673 switch (src_ptr) {
6756 .got_load,6674 .linker_load, .memory => {
6757 .direct_load,
6758 .imports_load,
6759 .memory,
6760 => {
6761 const reg = try self.register_manager.allocReg(null, gp);6675 const reg = try self.register_manager.allocReg(null, gp);
6762 try self.loadMemPtrIntoRegister(reg, src_ty, src_ptr);6676 try self.loadMemPtrIntoRegister(reg, src_ty, src_ptr);
6763 _ = try self.addInst(.{6677 _ = try self.addInst(.{
...@@ -6997,10 +6911,16 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne...@@ -6997,10 +6911,16 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
6997 return MCValue{ .memory = got_addr };6911 return MCValue{ .memory = got_addr };
6998 } else if (self.bin_file.cast(link.File.MachO)) |_| {6912 } else if (self.bin_file.cast(link.File.MachO)) |_| {
6999 assert(decl.link.macho.sym_index != 0);6913 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 } };
7001 } else if (self.bin_file.cast(link.File.Coff)) |_| {6918 } else if (self.bin_file.cast(link.File.Coff)) |_| {
7002 assert(decl.link.coff.sym_index != 0);6919 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 } };
7004 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {6924 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
7005 try p9.seeDecl(decl_index);6925 try p9.seeDecl(decl_index);
7006 const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes;6926 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 {...@@ -7019,9 +6939,15 @@ fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue {
7019 const vaddr = elf_file.local_symbols.items[local_sym_index].st_value;6939 const vaddr = elf_file.local_symbols.items[local_sym_index].st_value;
7020 return MCValue{ .memory = vaddr };6940 return MCValue{ .memory = vaddr };
7021 } else if (self.bin_file.cast(link.File.MachO)) |_| {6941 } 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 } };
7023 } else if (self.bin_file.cast(link.File.Coff)) |_| {6946 } 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 } };
7025 } else if (self.bin_file.cast(link.File.Plan9)) |_| {6951 } else if (self.bin_file.cast(link.File.Plan9)) |_| {
7026 return self.fail("TODO lower unnamed const in Plan9", .{});6952 return self.fail("TODO lower unnamed const in Plan9", .{});
7027 } else {6953 } else {
src/arch/x86_64/Emit.zig+11-8
...@@ -1021,10 +1021,14 @@ fn mirLeaPic(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {...@@ -1021,10 +1021,14 @@ fn mirLeaPic(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
1021 .@"type" = switch (ops.flags) {1021 .@"type" = switch (ops.flags) {
1022 0b00 => .got,1022 0b00 => .got,
1023 0b01 => .direct,1023 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),
1025 else => unreachable,1030 else => unreachable,
1026 },1031 },
1027 .target = .{ .sym_index = relocation.sym_index, .file = null },
1028 .offset = @intCast(u32, end_offset - 4),1032 .offset = @intCast(u32, end_offset - 4),
1029 .addend = 0,1033 .addend = 0,
1030 .pcrel = true,1034 .pcrel = true,
...@@ -1142,12 +1146,10 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {...@@ -1142,12 +1146,10 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
1142 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {1146 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
1143 // Add relocation to the decl.1147 // Add relocation to the decl.
1144 const atom = macho_file.atom_by_index_table.get(relocation.atom_index).?;1148 const atom = macho_file.atom_by_index_table.get(relocation.atom_index).?;
1149 const target = macho_file.getGlobalByIndex(relocation.sym_index);
1145 try atom.relocs.append(emit.bin_file.allocator, .{1150 try atom.relocs.append(emit.bin_file.allocator, .{
1146 .offset = offset,1151 .offset = offset,
1147 .target = .{1152 .target = target,
1148 .sym_index = relocation.sym_index,
1149 .file = null,
1150 },
1151 .addend = 0,1153 .addend = 0,
1152 .subtractor = null,1154 .subtractor = null,
1153 .pcrel = true,1155 .pcrel = true,
...@@ -1157,16 +1159,17 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {...@@ -1157,16 +1159,17 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
1157 } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {1159 } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
1158 // Add relocation to the decl.1160 // Add relocation to the decl.
1159 const atom = coff_file.atom_by_index_table.get(relocation.atom_index).?;1161 const atom = coff_file.atom_by_index_table.get(relocation.atom_index).?;
1162 const target = coff_file.getGlobalByIndex(relocation.sym_index);
1160 try atom.addRelocation(coff_file, .{1163 try atom.addRelocation(coff_file, .{
1161 .@"type" = .direct,1164 .@"type" = .direct,
1162 .target = .{ .sym_index = relocation.sym_index, .file = null },1165 .target = target,
1163 .offset = offset,1166 .offset = offset,
1164 .addend = 0,1167 .addend = 0,
1165 .pcrel = true,1168 .pcrel = true,
1166 .length = 2,1169 .length = 2,
1167 });1170 });
1168 } else {1171 } 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", .{});
1170 }1173 }
1171}1174}
11721175
src/link/Coff.zig+61-18
...@@ -127,7 +127,7 @@ pub const Reloc = struct {...@@ -127,7 +127,7 @@ pub const Reloc = struct {
127 @"type": enum {127 @"type": enum {
128 got,128 got,
129 direct,129 direct,
130 imports,130 import,
131 },131 },
132 target: SymbolWithLoc,132 target: SymbolWithLoc,
133 offset: u32,133 offset: u32,
...@@ -141,7 +141,7 @@ pub const Reloc = struct {...@@ -141,7 +141,7 @@ pub const Reloc = struct {
141 switch (self.@"type") {141 switch (self.@"type") {
142 .got => return coff_file.getGotAtomForSymbol(self.target),142 .got => return coff_file.getGotAtomForSymbol(self.target),
143 .direct => return coff_file.getAtomForSymbol(self.target),143 .direct => return coff_file.getAtomForSymbol(self.target),
144 .imports => return coff_file.getImportAtomForSymbol(self.target),144 .import => return coff_file.getImportAtomForSymbol(self.target),
145 }145 }
146 }146 }
147};147};
...@@ -1423,23 +1423,22 @@ fn resolveGlobalSymbol(self: *Coff, current: SymbolWithLoc) !void {...@@ -1423,23 +1423,22 @@ fn resolveGlobalSymbol(self: *Coff, current: SymbolWithLoc) !void {
1423 const sym = self.getSymbol(current);1423 const sym = self.getSymbol(current);
1424 const sym_name = self.getSymbolName(current);1424 const sym_name = self.getSymbolName(current);
14251425
1426 const global_index = self.resolver.get(sym_name) orelse {1426 const gop = try self.getOrPutGlobalPtr(sym_name);
1427 const name = try gpa.dupe(u8, sym_name);1427 if (!gop.found_existing) {
1428 const global_index = try self.allocateGlobal();1428 gop.value_ptr.* = current;
1429 self.globals.items[global_index] = current;
1430 try self.resolver.putNoClobber(gpa, name, global_index);
1431 if (sym.section_number == .UNDEFINED) {1429 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);
1433 }1431 }
1434 return;1432 return;
1435 };1433 }
14361434
1437 log.debug("TODO finish resolveGlobalSymbols implementation", .{});1435 log.debug("TODO finish resolveGlobalSymbols implementation", .{});
14381436
1439 if (sym.section_number == .UNDEFINED) return;1437 if (sym.section_number == .UNDEFINED) return;
14401438
1441 _ = self.unresolved.swapRemove(global_index);1439 _ = self.unresolved.swapRemove(self.getGlobalIndex(sym_name).?);
1442 self.globals.items[global_index] = current;1440
1441 gop.value_ptr.* = current;
1443}1442}
14441443
1445pub fn flush(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !void {1444pub fn flush(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !void {
...@@ -1544,25 +1543,26 @@ pub fn getDeclVAddr(...@@ -1544,25 +1543,26 @@ pub fn getDeclVAddr(
1544}1543}
15451544
1546pub fn getGlobalSymbol(self: *Coff, name: []const u8) !u32 {1545pub fn getGlobalSymbol(self: *Coff, name: []const u8) !u32 {
1547 if (self.resolver.get(name)) |global_index| {1546 const gop = try self.getOrPutGlobalPtr(name);
1548 return self.globals.items[global_index].sym_index;1547 const global_index = self.getGlobalIndex(name).?;
1548
1549 if (gop.found_existing) {
1550 return global_index;
1549 }1551 }
15501552
1551 const gpa = self.base.allocator;
1552 const sym_index = try self.allocateSymbol();1553 const sym_index = try self.allocateSymbol();
1553 const global_index = try self.allocateGlobal();
1554 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };1554 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;
1557 const sym_name = try gpa.dupe(u8, name);1558 const sym_name = try gpa.dupe(u8, name);
1558 const sym = self.getSymbolPtr(sym_loc);1559 const sym = self.getSymbolPtr(sym_loc);
1559 try self.setSymbolName(sym, sym_name);1560 try self.setSymbolName(sym, sym_name);
1560 sym.storage_class = .EXTERNAL;1561 sym.storage_class = .EXTERNAL;
15611562
1562 try self.resolver.putNoClobber(gpa, sym_name, global_index);
1563 try self.unresolved.putNoClobber(gpa, global_index, true);1563 try self.unresolved.putNoClobber(gpa, global_index, true);
15641564
1565 return sym_index;1565 return global_index;
1566}1566}
15671567
1568pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl: *Module.Decl) !void {1568pub 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 {...@@ -2061,6 +2061,49 @@ pub fn getSymbolName(self: *const Coff, sym_loc: SymbolWithLoc) []const u8 {
2061 return self.strtab.get(offset).?;2061 return self.strtab.get(offset).?;
2062}2062}
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
2064/// Returns atom if there is an atom referenced by the symbol described by `sym_loc` descriptor.2107/// Returns atom if there is an atom referenced by the symbol described by `sym_loc` descriptor.
2065/// Returns null on failure.2108/// Returns null on failure.
2066pub fn getAtomForSymbol(self: *Coff, sym_loc: SymbolWithLoc) ?*Atom {2109pub 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 {...@@ -111,13 +111,3 @@ pub fn addBaseRelocation(self: *Atom, coff_file: *Coff, offset: u32) !void {
111 }111 }
112 try gop.value_ptr.append(gpa, offset);112 try gop.value_ptr.append(gpa, offset);
113}113}
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,...@@ -131,17 +131,12 @@ la_symbol_ptr_section_index: ?u8 = null,
131data_section_index: ?u8 = null,131data_section_index: ?u8 = null,
132132
133locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},133locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
134globals: std.StringArrayHashMapUnmanaged(SymbolWithLoc) = .{},134globals: std.ArrayListUnmanaged(SymbolWithLoc) = .{},
135// FIXME Jakub135resolver: std.StringHashMapUnmanaged(u32) = .{},
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.
142unresolved: std.AutoArrayHashMapUnmanaged(u32, bool) = .{},136unresolved: std.AutoArrayHashMapUnmanaged(u32, bool) = .{},
143137
144locals_free_list: std.ArrayListUnmanaged(u32) = .{},138locals_free_list: std.ArrayListUnmanaged(u32) = .{},
139globals_free_list: std.ArrayListUnmanaged(u32) = .{},
145140
146dyld_stub_binder_index: ?u32 = null,141dyld_stub_binder_index: ?u32 = null,
147dyld_private_atom: ?*Atom = null,142dyld_private_atom: ?*Atom = null,
...@@ -1917,7 +1912,7 @@ fn allocateSpecialSymbols(self: *MachO) !void {...@@ -1917,7 +1912,7 @@ fn allocateSpecialSymbols(self: *MachO) !void {
1917 "___dso_handle",1912 "___dso_handle",
1918 "__mh_execute_header",1913 "__mh_execute_header",
1919 }) |name| {1914 }) |name| {
1920 const global = self.globals.get(name) orelse continue;1915 const global = self.getGlobal(name) orelse continue;
1921 if (global.file != null) continue;1916 if (global.file != null) continue;
1922 const sym = self.getSymbolPtr(global);1917 const sym = self.getSymbolPtr(global);
1923 const seg = self.segments.items[self.text_segment_cmd_index.?];1918 const seg = self.segments.items[self.text_segment_cmd_index.?];
...@@ -2048,16 +2043,11 @@ fn writeAtomsIncremental(self: *MachO) !void {...@@ -2048,16 +2043,11 @@ fn writeAtomsIncremental(self: *MachO) !void {
20482043
2049pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !*Atom {2044pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !*Atom {
2050 const gpa = self.base.allocator;2045 const gpa = self.base.allocator;
2051 const sym_index = @intCast(u32, self.locals.items.len);2046 const sym_index = try self.allocateSymbol();
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
2060 const atom = try MachO.createEmptyAtom(gpa, sym_index, @sizeOf(u64), 3);2047 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
2061 try atom.relocs.append(gpa, .{2051 try atom.relocs.append(gpa, .{
2062 .offset = 0,2052 .offset = 0,
2063 .target = target,2053 .target = target,
...@@ -2074,7 +2064,7 @@ pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !*Atom {...@@ -2074,7 +2064,7 @@ pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !*Atom {
20742064
2075 const target_sym = self.getSymbol(target);2065 const target_sym = self.getSymbol(target);
2076 if (target_sym.undf()) {2066 if (target_sym.undf()) {
2077 const global = self.globals.get(self.getSymbolName(target)).?;2067 const global = self.getGlobal(self.getSymbolName(target)).?;
2078 try atom.bindings.append(gpa, .{2068 try atom.bindings.append(gpa, .{
2079 .target = global,2069 .target = global,
2080 .offset = 0,2070 .offset = 0,
...@@ -2093,20 +2083,15 @@ pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !*Atom {...@@ -2093,20 +2083,15 @@ pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !*Atom {
20932083
2094pub fn createTlvPtrAtom(self: *MachO, target: SymbolWithLoc) !*Atom {2084pub fn createTlvPtrAtom(self: *MachO, target: SymbolWithLoc) !*Atom {
2095 const gpa = self.base.allocator;2085 const gpa = self.base.allocator;
2096 const sym_index = @intCast(u32, self.locals.items.len);2086 const sym_index = try self.allocateSymbol();
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
2105 const atom = try MachO.createEmptyAtom(gpa, sym_index, @sizeOf(u64), 3);2087 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
2106 const target_sym = self.getSymbol(target);2091 const target_sym = self.getSymbol(target);
2107 assert(target_sym.undf());2092 assert(target_sym.undf());
21082093
2109 const global = self.globals.get(self.getSymbolName(target)).?;2094 const global = self.getGlobal(self.getSymbolName(target)).?;
2110 try atom.bindings.append(gpa, .{2095 try atom.bindings.append(gpa, .{
2111 .target = global,2096 .target = global,
2112 .offset = 0,2097 .offset = 0,
...@@ -2130,15 +2115,10 @@ fn createDyldPrivateAtom(self: *MachO) !void {...@@ -2130,15 +2115,10 @@ fn createDyldPrivateAtom(self: *MachO) !void {
2130 if (self.dyld_private_atom != null) return;2115 if (self.dyld_private_atom != null) return;
21312116
2132 const gpa = self.base.allocator;2117 const gpa = self.base.allocator;
2133 const sym_index = @intCast(u32, self.locals.items.len);2118 const sym_index = try self.allocateSymbol();
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 });
2141 const atom = try MachO.createEmptyAtom(gpa, sym_index, @sizeOf(u64), 3);2119 const atom = try MachO.createEmptyAtom(gpa, sym_index, @sizeOf(u64), 3);
2120 const sym = atom.getSymbolPtr(self);
2121 sym.n_type = macho.N_SECT;
2142 self.dyld_private_atom = atom;2122 self.dyld_private_atom = atom;
21432123
2144 try self.allocateAtomCommon(atom, self.data_section_index.?);2124 try self.allocateAtomCommon(atom, self.data_section_index.?);
...@@ -2163,15 +2143,11 @@ fn createStubHelperPreambleAtom(self: *MachO) !void {...@@ -2163,15 +2143,11 @@ fn createStubHelperPreambleAtom(self: *MachO) !void {
2163 .aarch64 => 2,2143 .aarch64 => 2,
2164 else => unreachable,2144 else => unreachable,
2165 };2145 };
2166 const sym_index = @intCast(u32, self.locals.items.len);2146 const sym_index = try self.allocateSymbol();
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 });
2174 const atom = try MachO.createEmptyAtom(gpa, sym_index, size, alignment);2147 const atom = try MachO.createEmptyAtom(gpa, sym_index, size, alignment);
2148 const sym = atom.getSymbolPtr(self);
2149 sym.n_type = macho.N_SECT;
2150
2175 const dyld_private_sym_index = self.dyld_private_atom.?.sym_index;2151 const dyld_private_sym_index = self.dyld_private_atom.?.sym_index;
2176 switch (arch) {2152 switch (arch) {
2177 .x86_64 => {2153 .x86_64 => {
...@@ -2288,15 +2264,11 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom {...@@ -2288,15 +2264,11 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom {
2288 .aarch64 => 2,2264 .aarch64 => 2,
2289 else => unreachable,2265 else => unreachable,
2290 };2266 };
2291 const sym_index = @intCast(u32, self.locals.items.len);2267 const sym_index = try self.allocateSymbol();
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 });
2299 const atom = try MachO.createEmptyAtom(gpa, sym_index, stub_size, alignment);2268 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
2300 try atom.relocs.ensureTotalCapacity(gpa, 1);2272 try atom.relocs.ensureTotalCapacity(gpa, 1);
23012273
2302 switch (arch) {2274 switch (arch) {
...@@ -2352,15 +2324,11 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom {...@@ -2352,15 +2324,11 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom {
23522324
2353pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, target: SymbolWithLoc) !*Atom {2325pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, target: SymbolWithLoc) !*Atom {
2354 const gpa = self.base.allocator;2326 const gpa = self.base.allocator;
2355 const sym_index = @intCast(u32, self.locals.items.len);2327 const sym_index = try self.allocateSymbol();
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 });
2363 const atom = try MachO.createEmptyAtom(gpa, sym_index, @sizeOf(u64), 3);2328 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
2364 try atom.relocs.append(gpa, .{2332 try atom.relocs.append(gpa, .{
2365 .offset = 0,2333 .offset = 0,
2366 .target = .{ .sym_index = stub_sym_index, .file = null },2334 .target = .{ .sym_index = stub_sym_index, .file = null },
...@@ -2376,7 +2344,7 @@ pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, target: SymbolWi...@@ -2376,7 +2344,7 @@ pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, target: SymbolWi
2376 });2344 });
2377 try atom.rebases.append(gpa, 0);2345 try atom.rebases.append(gpa, 0);
23782346
2379 const global = self.globals.get(self.getSymbolName(target)).?;2347 const global = self.getGlobal(self.getSymbolName(target)).?;
2380 try atom.lazy_bindings.append(gpa, .{2348 try atom.lazy_bindings.append(gpa, .{
2381 .target = global,2349 .target = global,
2382 .offset = 0,2350 .offset = 0,
...@@ -2403,15 +2371,11 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {...@@ -2403,15 +2371,11 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {
2403 .aarch64 => 3 * @sizeOf(u32),2371 .aarch64 => 3 * @sizeOf(u32),
2404 else => unreachable, // unhandled architecture type2372 else => unreachable, // unhandled architecture type
2405 };2373 };
2406 const sym_index = @intCast(u32, self.locals.items.len);2374 const sym_index = try self.allocateSymbol();
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 });
2414 const atom = try MachO.createEmptyAtom(gpa, sym_index, stub_size, alignment);2375 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
2415 switch (arch) {2379 switch (arch) {
2416 .x86_64 => {2380 .x86_64 => {
2417 // jmp2381 // jmp
...@@ -2472,7 +2436,7 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {...@@ -2472,7 +2436,7 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {
2472fn createTentativeDefAtoms(self: *MachO) !void {2436fn createTentativeDefAtoms(self: *MachO) !void {
2473 const gpa = self.base.allocator;2437 const gpa = self.base.allocator;
24742438
2475 for (self.globals.values()) |global| {2439 for (self.globals.items) |global| {
2476 const sym = self.getSymbolPtr(global);2440 const sym = self.getSymbolPtr(global);
2477 if (!sym.tentative()) continue;2441 if (!sym.tentative()) continue;
24782442
...@@ -2516,51 +2480,44 @@ fn createTentativeDefAtoms(self: *MachO) !void {...@@ -2516,51 +2480,44 @@ fn createTentativeDefAtoms(self: *MachO) !void {
25162480
2517fn createMhExecuteHeaderSymbol(self: *MachO) !void {2481fn createMhExecuteHeaderSymbol(self: *MachO) !void {
2518 if (self.base.options.output_mode != .Exe) return;2482 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| {
2520 const sym = self.getSymbol(global);2484 const sym = self.getSymbol(global);
2521 if (!sym.undf() and !(sym.pext() or sym.weakDef())) return;2485 if (!sym.undf() and !(sym.pext() or sym.weakDef())) return;
2522 }2486 }
25232487
2524 const gpa = self.base.allocator;2488 const gpa = self.base.allocator;
2525 const n_strx = try self.strtab.insert(gpa, "__mh_execute_header");2489 const sym_index = try self.allocateSymbol();
2526 const sym_index = @intCast(u32, self.locals.items.len);2490 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };
2527 try self.locals.append(gpa, .{2491 const sym = self.getSymbolPtr(sym_loc);
2528 .n_strx = n_strx,2492 sym.* = .{
2493 .n_strx = try self.strtab.insert(gpa, "__mh_execute_header"),
2529 .n_type = macho.N_SECT | macho.N_EXT,2494 .n_type = macho.N_SECT | macho.N_EXT,
2530 .n_sect = 0,2495 .n_sect = 0,
2531 .n_desc = macho.REFERENCED_DYNAMICALLY,2496 .n_desc = macho.REFERENCED_DYNAMICALLY,
2532 .n_value = 0,2497 .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,
2541 };2498 };
2499
2500 const gop = try self.getOrPutGlobalPtr("__mh_execute_header");
2501 gop.value_ptr.* = sym_loc;
2542}2502}
25432503
2544fn createDsoHandleSymbol(self: *MachO) !void {2504fn createDsoHandleSymbol(self: *MachO) !void {
2545 const global = self.globals.getPtr("___dso_handle") orelse return;2505 const global = self.getGlobalPtr("___dso_handle") orelse return;
2546 const sym = self.getSymbolPtr(global.*);2506 if (!self.getSymbol(global.*).undf()) return;
2547 if (!sym.undf()) return;
25482507
2549 const gpa = self.base.allocator;2508 const gpa = self.base.allocator;
2550 const n_strx = try self.strtab.insert(gpa, "___dso_handle");2509 const sym_index = try self.allocateSymbol();
2551 const sym_index = @intCast(u32, self.locals.items.len);2510 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };
2552 try self.locals.append(gpa, .{2511 const sym = self.getSymbolPtr(sym_loc);
2553 .n_strx = n_strx,2512 sym.* = .{
2513 .n_strx = try self.strtab.insert(gpa, "___dso_handle"),
2554 .n_type = macho.N_SECT | macho.N_EXT,2514 .n_type = macho.N_SECT | macho.N_EXT,
2555 .n_sect = 0,2515 .n_sect = 0,
2556 .n_desc = macho.N_WEAK_DEF,2516 .n_desc = macho.N_WEAK_DEF,
2557 .n_value = 0,2517 .n_value = 0,
2558 });
2559 global.* = .{
2560 .sym_index = sym_index,
2561 .file = null,
2562 };2518 };
2563 _ = self.unresolved.swapRemove(@intCast(u32, self.globals.getIndex("___dso_handle").?));2519 global.* = sym_loc;
2520 _ = self.unresolved.swapRemove(self.getGlobalIndex("___dso_handle").?);
2564}2521}
25652522
2566fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void {2523fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void {
...@@ -2568,19 +2525,14 @@ fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void {...@@ -2568,19 +2525,14 @@ fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void {
2568 const sym = self.getSymbol(current);2525 const sym = self.getSymbol(current);
2569 const sym_name = self.getSymbolName(current);2526 const sym_name = self.getSymbolName(current);
25702527
2571 const name = try gpa.dupe(u8, sym_name);2528 const gop = try self.getOrPutGlobalPtr(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
2576 if (!gop.found_existing) {2529 if (!gop.found_existing) {
2577 gop.value_ptr.* = current;2530 gop.value_ptr.* = current;
2578 if (sym.undf() and !sym.tentative()) {2531 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);
2580 }2533 }
2581 return;2534 return;
2582 }2535 }
2583
2584 const global = gop.value_ptr.*;2536 const global = gop.value_ptr.*;
2585 const global_sym = self.getSymbol(global);2537 const global_sym = self.getSymbol(global);
25862538
...@@ -2619,7 +2571,7 @@ fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void {...@@ -2619,7 +2571,7 @@ fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void {
2619 }2571 }
2620 if (sym.undf() and !sym.tentative()) return;2572 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
2624 gop.value_ptr.* = current;2576 gop.value_ptr.* = current;
2625}2577}
...@@ -2664,7 +2616,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {...@@ -2664,7 +2616,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
2664 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = object_id };2616 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = object_id };
2665 self.resolveGlobalSymbol(sym_loc) catch |err| switch (err) {2617 self.resolveGlobalSymbol(sym_loc) catch |err| switch (err) {
2666 error.MultipleSymbolDefinitions => {2618 error.MultipleSymbolDefinitions => {
2667 const global = self.globals.get(sym_name).?;2619 const global = self.getGlobal(sym_name).?;
2668 log.err("symbol '{s}' defined multiple times", .{sym_name});2620 log.err("symbol '{s}' defined multiple times", .{sym_name});
2669 if (global.file) |file| {2621 if (global.file) |file| {
2670 log.err(" first definition in '{s}'", .{self.objects.items[file].name});2622 log.err(" first definition in '{s}'", .{self.objects.items[file].name});
...@@ -2684,7 +2636,8 @@ fn resolveSymbolsInArchives(self: *MachO) !void {...@@ -2684,7 +2636,8 @@ fn resolveSymbolsInArchives(self: *MachO) !void {
2684 const cpu_arch = self.base.options.target.cpu.arch;2636 const cpu_arch = self.base.options.target.cpu.arch;
2685 var next_sym: usize = 0;2637 var next_sym: usize = 0;
2686 loop: while (next_sym < self.unresolved.count()) {2638 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];
2688 const sym_name = self.getSymbolName(global);2641 const sym_name = self.getSymbolName(global);
26892642
2690 for (self.archives.items) |archive| {2643 for (self.archives.items) |archive| {
...@@ -2710,10 +2663,11 @@ fn resolveSymbolsInArchives(self: *MachO) !void {...@@ -2710,10 +2663,11 @@ fn resolveSymbolsInArchives(self: *MachO) !void {
2710fn resolveSymbolsInDylibs(self: *MachO) !void {2663fn resolveSymbolsInDylibs(self: *MachO) !void {
2711 if (self.dylibs.items.len == 0) return;2664 if (self.dylibs.items.len == 0) return;
27122665
2666 const gpa = self.base.allocator;
2713 var next_sym: usize = 0;2667 var next_sym: usize = 0;
2714 loop: while (next_sym < self.unresolved.count()) {2668 loop: while (next_sym < self.unresolved.count()) {
2715 const global_index = self.unresolved.keys()[next_sym];2669 const global_index = self.unresolved.keys()[next_sym];
2716 const global = self.globals.values()[global_index];2670 const global = self.globals.items[global_index];
2717 const sym = self.getSymbolPtr(global);2671 const sym = self.getSymbolPtr(global);
2718 const sym_name = self.getSymbolName(global);2672 const sym_name = self.getSymbolName(global);
27192673
...@@ -2722,7 +2676,7 @@ fn resolveSymbolsInDylibs(self: *MachO) !void {...@@ -2722,7 +2676,7 @@ fn resolveSymbolsInDylibs(self: *MachO) !void {
27222676
2723 const dylib_id = @intCast(u16, id);2677 const dylib_id = @intCast(u16, id);
2724 if (!self.referenced_dylibs.contains(dylib_id)) {2678 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, {});
2726 }2680 }
27272681
2728 const ordinal = self.referenced_dylibs.getIndex(dylib_id) orelse unreachable;2682 const ordinal = self.referenced_dylibs.getIndex(dylib_id) orelse unreachable;
...@@ -2760,7 +2714,7 @@ fn resolveSymbolsAtLoading(self: *MachO) !void {...@@ -2760,7 +2714,7 @@ fn resolveSymbolsAtLoading(self: *MachO) !void {
2760 var next_sym: usize = 0;2714 var next_sym: usize = 0;
2761 while (next_sym < self.unresolved.count()) {2715 while (next_sym < self.unresolved.count()) {
2762 const global_index = self.unresolved.keys()[next_sym];2716 const global_index = self.unresolved.keys()[next_sym];
2763 const global = self.globals.values()[global_index];2717 const global = self.globals.items[global_index];
2764 const sym = self.getSymbolPtr(global);2718 const sym = self.getSymbolPtr(global);
2765 const sym_name = self.getSymbolName(global);2719 const sym_name = self.getSymbolName(global);
27662720
...@@ -2800,26 +2754,27 @@ fn resolveDyldStubBinder(self: *MachO) !void {...@@ -2800,26 +2754,27 @@ fn resolveDyldStubBinder(self: *MachO) !void {
2800 if (self.unresolved.count() == 0) return; // no need for a stub binder if we don't have any imports2754 if (self.unresolved.count() == 0) return; // no need for a stub binder if we don't have any imports
28012755
2802 const gpa = self.base.allocator;2756 const gpa = self.base.allocator;
2803 const n_strx = try self.strtab.insert(gpa, "dyld_stub_binder");2757 const sym_index = try self.allocateSymbol();
2804 const sym_index = @intCast(u32, self.locals.items.len);2758 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };
2805 try self.locals.append(gpa, .{2759 const sym = self.getSymbolPtr(sym_loc);
2806 .n_strx = n_strx,2760 const sym_name = "dyld_stub_binder";
2761 sym.* = .{
2762 .n_strx = try self.strtab.insert(gpa, sym_name),
2807 .n_type = macho.N_UNDF,2763 .n_type = macho.N_UNDF,
2808 .n_sect = 0,2764 .n_sect = 0,
2809 .n_desc = 0,2765 .n_desc = 0,
2810 .n_value = 0,2766 .n_value = 0,
2811 });2767 };
2812 const sym_name = try gpa.dupe(u8, "dyld_stub_binder");2768 const gop = try self.getOrPutGlobalPtr(sym_name);
2813 const global = SymbolWithLoc{ .sym_index = sym_index, .file = null };2769 gop.value_ptr.* = sym_loc;
2814 try self.globals.putNoClobber(gpa, sym_name, global);2770 const global = gop.value_ptr.*;
2815 const sym = &self.locals.items[sym_index];
28162771
2817 for (self.dylibs.items) |dylib, id| {2772 for (self.dylibs.items) |dylib, id| {
2818 if (!dylib.symbols.contains(sym_name)) continue;2773 if (!dylib.symbols.contains(sym_name)) continue;
28192774
2820 const dylib_id = @intCast(u16, id);2775 const dylib_id = @intCast(u16, id);
2821 if (!self.referenced_dylibs.contains(dylib_id)) {2776 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, {});
2823 }2778 }
28242779
2825 const ordinal = self.referenced_dylibs.getIndex(dylib_id) orelse unreachable;2780 const ordinal = self.referenced_dylibs.getIndex(dylib_id) orelse unreachable;
...@@ -3050,14 +3005,20 @@ pub fn deinit(self: *MachO) void {...@@ -3050,14 +3005,20 @@ pub fn deinit(self: *MachO) void {
3050 self.stubs_free_list.deinit(gpa);3005 self.stubs_free_list.deinit(gpa);
3051 self.stubs_table.deinit(gpa);3006 self.stubs_table.deinit(gpa);
3052 self.strtab.deinit(gpa);3007 self.strtab.deinit(gpa);
3008
3053 self.locals.deinit(gpa);3009 self.locals.deinit(gpa);
3010 self.globals.deinit(gpa);
3054 self.locals_free_list.deinit(gpa);3011 self.locals_free_list.deinit(gpa);
3012 self.globals_free_list.deinit(gpa);
3055 self.unresolved.deinit(gpa);3013 self.unresolved.deinit(gpa);
30563014
3057 for (self.globals.keys()) |key| {3015 {
3058 gpa.free(key);3016 var it = self.resolver.keyIterator();
3017 while (it.next()) |key_ptr| {
3018 gpa.free(key_ptr.*);
3019 }
3020 self.resolver.deinit(gpa);
3059 }3021 }
3060 self.globals.deinit(gpa);
30613022
3062 for (self.objects.items) |*object| {3023 for (self.objects.items) |*object| {
3063 object.deinit(gpa);3024 object.deinit(gpa);
...@@ -3211,6 +3172,29 @@ fn allocateSymbol(self: *MachO) !u32 {...@@ -3211,6 +3172,29 @@ fn allocateSymbol(self: *MachO) !u32 {
3211 return index;3172 return index;
3212}3173}
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
3214pub fn allocateGotEntry(self: *MachO, target: SymbolWithLoc) !u32 {3198pub fn allocateGotEntry(self: *MachO, target: SymbolWithLoc) !u32 {
3215 const gpa = self.base.allocator;3199 const gpa = self.base.allocator;
3216 try self.got_entries.ensureUnusedCapacity(gpa, 1);3200 try self.got_entries.ensureUnusedCapacity(gpa, 1);
...@@ -3832,7 +3816,7 @@ pub fn updateDeclExports(...@@ -3832,7 +3816,7 @@ pub fn updateDeclExports(
38323816
3833 self.resolveGlobalSymbol(sym_loc) catch |err| switch (err) {3817 self.resolveGlobalSymbol(sym_loc) catch |err| switch (err) {
3834 error.MultipleSymbolDefinitions => {3818 error.MultipleSymbolDefinitions => {
3835 const global = self.globals.get(exp_name).?;3819 const global = self.getGlobal(exp_name).?;
3836 if (sym_loc.sym_index != global.sym_index and global.file != null) {3820 if (sym_loc.sym_index != global.sym_index and global.file != null) {
3837 _ = try module.failed_exports.put(module.gpa, exp, try Module.ErrorMsg.create(3821 _ = try module.failed_exports.put(module.gpa, exp, try Module.ErrorMsg.create(
3838 gpa,3822 gpa,
...@@ -3869,11 +3853,13 @@ pub fn deleteExport(self: *MachO, exp: Export) void {...@@ -3869,11 +3853,13 @@ pub fn deleteExport(self: *MachO, exp: Export) void {
3869 };3853 };
3870 self.locals_free_list.append(gpa, sym_index) catch {};3854 self.locals_free_list.append(gpa, sym_index) catch {};
38713855
3872 if (self.globals.get(sym_name)) |global| blk: {3856 if (self.resolver.fetchRemove(sym_name)) |entry| {
3873 if (global.sym_index != sym_index) break :blk;3857 defer gpa.free(entry.key);
3874 if (global.file != null) break :blk;3858 self.globals_free_list.append(gpa, entry.value) catch {};
3875 const kv = self.globals.fetchSwapRemove(sym_name);3859 self.globals.items[entry.value] = .{
3876 gpa.free(kv.?.key);3860 .sym_index = 0,
3861 .file = null,
3862 };
3877 }3863 }
3878}3864}
38793865
...@@ -4864,32 +4850,26 @@ pub fn addAtomToSection(self: *MachO, atom: *Atom, sect_id: u8) !void {...@@ -4864,32 +4850,26 @@ pub fn addAtomToSection(self: *MachO, atom: *Atom, sect_id: u8) !void {
48644850
4865pub fn getGlobalSymbol(self: *MachO, name: []const u8) !u32 {4851pub fn getGlobalSymbol(self: *MachO, name: []const u8) !u32 {
4866 const gpa = self.base.allocator;4852 const gpa = self.base.allocator;
4853
4867 const sym_name = try std.fmt.allocPrint(gpa, "_{s}", .{name});4854 const sym_name = try std.fmt.allocPrint(gpa, "_{s}", .{name});
4868 const global_index = @intCast(u32, self.globals.values().len);4855 defer gpa.free(sym_name);
4869 const gop = try self.globals.getOrPut(gpa, sym_name);4856 const gop = try self.getOrPutGlobalPtr(sym_name);
4870 defer if (gop.found_existing) gpa.free(sym_name);4857 const global_index = self.getGlobalIndex(sym_name).?;
48714858
4872 if (gop.found_existing) {4859 if (gop.found_existing) {
4873 // TODO audit this: can we ever reference anything from outside the Zig module?4860 return global_index;
4874 assert(gop.value_ptr.file == null);
4875 return gop.value_ptr.sym_index;
4876 }4861 }
48774862
4878 const sym_index = @intCast(u32, self.locals.items.len);4863 const sym_index = try self.allocateSymbol();
4879 try self.locals.append(gpa, .{4864 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };
4880 .n_strx = try self.strtab.insert(gpa, sym_name),4865 gop.value_ptr.* = sym_loc;
4881 .n_type = macho.N_UNDF,4866
4882 .n_sect = 0,4867 const sym = self.getSymbolPtr(sym_loc);
4883 .n_desc = 0,4868 sym.n_strx = try self.strtab.insert(gpa, sym_name);
4884 .n_value = 0,4869
4885 });
4886 gop.value_ptr.* = .{
4887 .sym_index = sym_index,
4888 .file = null,
4889 };
4890 try self.unresolved.putNoClobber(gpa, global_index, true);4870 try self.unresolved.putNoClobber(gpa, global_index, true);
48914871
4892 return sym_index;4872 return global_index;
4893}4873}
48944874
4895fn getSegmentAllocBase(self: MachO, indices: []const ?u8) struct { vmaddr: u64, fileoff: u64 } {4875fn 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 {...@@ -5055,7 +5035,7 @@ fn writeDyldInfoData(self: *MachO, ncmds: *u32, lc_writer: anytype) !void {
5055 if (self.base.options.output_mode == .Exe) {5035 if (self.base.options.output_mode == .Exe) {
5056 for (&[_]SymbolWithLoc{5036 for (&[_]SymbolWithLoc{
5057 try self.getEntryPoint(),5037 try self.getEntryPoint(),
5058 self.globals.get("__mh_execute_header").?,5038 self.getGlobal("__mh_execute_header").?,
5059 }) |global| {5039 }) |global| {
5060 const sym = self.getSymbol(global);5040 const sym = self.getSymbol(global);
5061 const sym_name = self.getSymbolName(global);5041 const sym_name = self.getSymbolName(global);
...@@ -5068,7 +5048,7 @@ fn writeDyldInfoData(self: *MachO, ncmds: *u32, lc_writer: anytype) !void {...@@ -5068,7 +5048,7 @@ fn writeDyldInfoData(self: *MachO, ncmds: *u32, lc_writer: anytype) !void {
5068 }5048 }
5069 } else {5049 } else {
5070 assert(self.base.options.output_mode == .Lib);5050 assert(self.base.options.output_mode == .Lib);
5071 for (self.globals.values()) |global| {5051 for (self.globals.items) |global| {
5072 const sym = self.getSymbol(global);5052 const sym = self.getSymbol(global);
50735053
5074 if (sym.undf()) continue;5054 if (sym.undf()) continue;
...@@ -5271,9 +5251,9 @@ fn writeFunctionStarts(self: *MachO, ncmds: *u32, lc_writer: anytype) !void {...@@ -5271,9 +5251,9 @@ fn writeFunctionStarts(self: *MachO, ncmds: *u32, lc_writer: anytype) !void {
5271 // We need to sort by address first5251 // We need to sort by address first
5272 var addresses = std.ArrayList(u64).init(gpa);5252 var addresses = std.ArrayList(u64).init(gpa);
5273 defer addresses.deinit();5253 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| {
5277 const sym = self.getSymbol(global);5257 const sym = self.getSymbol(global);
5278 if (sym.undf()) continue;5258 if (sym.undf()) continue;
5279 if (sym.n_desc == N_DESC_GCED) continue;5259 if (sym.n_desc == N_DESC_GCED) continue;
...@@ -5453,7 +5433,7 @@ fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx {...@@ -5453,7 +5433,7 @@ fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx {
5453 if (sym.n_desc == N_DESC_GCED) continue; // GCed, skip5433 if (sym.n_desc == N_DESC_GCED) continue; // GCed, skip
5454 const sym_loc = SymbolWithLoc{ .sym_index = @intCast(u32, sym_id), .file = null };5434 const sym_loc = SymbolWithLoc{ .sym_index = @intCast(u32, sym_id), .file = null };
5455 if (self.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip5435 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, skip5436 if (self.getGlobal(self.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip
5457 try locals.append(sym);5437 try locals.append(sym);
5458 }5438 }
54595439
...@@ -5463,7 +5443,7 @@ fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx {...@@ -5463,7 +5443,7 @@ fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx {
5463 if (sym.n_desc == N_DESC_GCED) continue; // GCed, skip5443 if (sym.n_desc == N_DESC_GCED) continue; // GCed, skip
5464 const sym_loc = SymbolWithLoc{ .sym_index = @intCast(u32, sym_id), .file = @intCast(u32, object_id) };5444 const sym_loc = SymbolWithLoc{ .sym_index = @intCast(u32, sym_id), .file = @intCast(u32, object_id) };
5465 if (self.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip5445 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, skip5446 if (self.getGlobal(self.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip
5467 var out_sym = sym;5447 var out_sym = sym;
5468 out_sym.n_strx = try self.strtab.insert(gpa, self.getSymbolName(sym_loc));5448 out_sym.n_strx = try self.strtab.insert(gpa, self.getSymbolName(sym_loc));
5469 try locals.append(out_sym);5449 try locals.append(out_sym);
...@@ -5477,7 +5457,7 @@ fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx {...@@ -5477,7 +5457,7 @@ fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx {
5477 var exports = std.ArrayList(macho.nlist_64).init(gpa);5457 var exports = std.ArrayList(macho.nlist_64).init(gpa);
5478 defer exports.deinit();5458 defer exports.deinit();
54795459
5480 for (self.globals.values()) |global| {5460 for (self.globals.items) |global| {
5481 const sym = self.getSymbol(global);5461 const sym = self.getSymbol(global);
5482 if (sym.undf()) continue; // import, skip5462 if (sym.undf()) continue; // import, skip
5483 if (sym.n_desc == N_DESC_GCED) continue; // GCed, skip5463 if (sym.n_desc == N_DESC_GCED) continue; // GCed, skip
...@@ -5491,7 +5471,7 @@ fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx {...@@ -5491,7 +5471,7 @@ fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx {
54915471
5492 var imports_table = std.AutoHashMap(SymbolWithLoc, u32).init(gpa);5472 var imports_table = std.AutoHashMap(SymbolWithLoc, u32).init(gpa);
54935473
5494 for (self.globals.values()) |global| {5474 for (self.globals.items) |global| {
5495 const sym = self.getSymbol(global);5475 const sym = self.getSymbol(global);
5496 if (sym.n_strx == 0) continue; // no name, skip5476 if (sym.n_strx == 0) continue; // no name, skip
5497 if (!sym.undf()) continue; // not an import, skip5477 if (!sym.undf()) continue; // not an import, skip
...@@ -5798,6 +5778,49 @@ pub fn getSymbolName(self: *MachO, sym_with_loc: SymbolWithLoc) []const u8 {...@@ -5798,6 +5778,49 @@ pub fn getSymbolName(self: *MachO, sym_with_loc: SymbolWithLoc) []const u8 {
5798 }5778 }
5799}5779}
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
5801/// Returns atom if there is an atom referenced by the symbol described by `sym_with_loc` descriptor.5824/// Returns atom if there is an atom referenced by the symbol described by `sym_with_loc` descriptor.
5802/// Returns null on failure.5825/// Returns null on failure.
5803pub fn getAtomForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?*Atom {5826pub fn getAtomForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?*Atom {
...@@ -5834,7 +5857,7 @@ pub fn getTlvPtrAtomForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?*Atom...@@ -5834,7 +5857,7 @@ pub fn getTlvPtrAtomForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?*Atom
5834/// Asserts output mode is executable.5857/// Asserts output mode is executable.
5835pub fn getEntryPoint(self: MachO) error{MissingMainEntrypoint}!SymbolWithLoc {5858pub fn getEntryPoint(self: MachO) error{MissingMainEntrypoint}!SymbolWithLoc {
5836 const entry_name = self.base.options.entry orelse "_main";5859 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 {
5838 log.err("entrypoint '{s}' not found", .{entry_name});5861 log.err("entrypoint '{s}' not found", .{entry_name});
5839 return error.MissingMainEntrypoint;5862 return error.MissingMainEntrypoint;
5840 };5863 };
...@@ -6342,9 +6365,9 @@ fn logSymtab(self: *MachO) void {...@@ -6342,9 +6365,9 @@ fn logSymtab(self: *MachO) void {
6342 }6365 }
63436366
6344 log.debug("globals table:", .{});6367 log.debug("globals table:", .{});
6345 for (self.globals.keys()) |name, id| {6368 for (self.globals.items) |global| {
6346 const value = self.globals.values()[id];6369 const name = self.getSymbolName(global);
6347 log.debug(" {s} => %{d} in object({?d})", .{ name, value.sym_index, value.file });6370 log.debug(" {s} => %{d} in object({?d})", .{ name, global.sym_index, global.file });
6348 }6371 }
63496372
6350 log.debug("GOT entries:", .{});6373 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,...@@ -272,7 +272,7 @@ pub fn parseRelocs(self: *Atom, relocs: []align(1) const macho.relocation_info,
272 subtractor = sym_loc;272 subtractor = sym_loc;
273 } else {273 } else {
274 const sym_name = context.macho_file.getSymbolName(sym_loc);274 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).?;
276 }276 }
277 // Verify that *_SUBTRACTOR is followed by *_UNSIGNED.277 // Verify that *_SUBTRACTOR is followed by *_UNSIGNED.
278 if (relocs.len <= i + 1) {278 if (relocs.len <= i + 1) {
...@@ -339,7 +339,7 @@ pub fn parseRelocs(self: *Atom, relocs: []align(1) const macho.relocation_info,...@@ -339,7 +339,7 @@ pub fn parseRelocs(self: *Atom, relocs: []align(1) const macho.relocation_info,
339 break :target sym_loc;339 break :target sym_loc;
340 } else {340 } else {
341 const sym_name = context.macho_file.getSymbolName(sym_loc);341 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).?;
343 }343 }
344 };344 };
345 const offset = @intCast(u32, rel.r_address - context.base_offset);345 const offset = @intCast(u32, rel.r_address - context.base_offset);
...@@ -579,7 +579,7 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void {...@@ -579,7 +579,7 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void {
579 // If there is no atom for target, we still need to check for special, atom-less579 // If there is no atom for target, we still need to check for special, atom-less
580 // symbols such as `___dso_handle`.580 // symbols such as `___dso_handle`.
581 const target_name = macho_file.getSymbolName(rel.target);581 const target_name = macho_file.getSymbolName(rel.target);
582 assert(macho_file.globals.contains(target_name));582 assert(macho_file.getGlobal(target_name) != null);
583 const atomless_sym = macho_file.getSymbol(rel.target);583 const atomless_sym = macho_file.getSymbol(rel.target);
584 log.debug(" | atomless target '{s}'", .{target_name});584 log.debug(" | atomless target '{s}'", .{target_name});
585 break :blk atomless_sym.n_value;585 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 {...@@ -480,7 +480,7 @@ fn writeSymtab(self: *DebugSymbols, lc: *macho.symtab_command) !void {
480 if (sym.n_desc == MachO.N_DESC_GCED) continue; // GCed, skip480 if (sym.n_desc == MachO.N_DESC_GCED) continue; // GCed, skip
481 const sym_loc = MachO.SymbolWithLoc{ .sym_index = @intCast(u32, sym_id), .file = null };481 const sym_loc = MachO.SymbolWithLoc{ .sym_index = @intCast(u32, sym_id), .file = null };
482 if (self.base.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip482 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, skip483 if (self.base.getGlobal(self.base.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip
484 var out_sym = sym;484 var out_sym = sym;
485 out_sym.n_strx = try self.strtab.insert(gpa, self.base.getSymbolName(sym_loc));485 out_sym.n_strx = try self.strtab.insert(gpa, self.base.getSymbolName(sym_loc));
486 try locals.append(out_sym);486 try locals.append(out_sym);
...@@ -489,7 +489,7 @@ fn writeSymtab(self: *DebugSymbols, lc: *macho.symtab_command) !void {...@@ -489,7 +489,7 @@ fn writeSymtab(self: *DebugSymbols, lc: *macho.symtab_command) !void {
489 var exports = std.ArrayList(macho.nlist_64).init(gpa);489 var exports = std.ArrayList(macho.nlist_64).init(gpa);
490 defer exports.deinit();490 defer exports.deinit();
491491
492 for (self.base.globals.values()) |global| {492 for (self.base.globals.items) |global| {
493 const sym = self.base.getSymbol(global);493 const sym = self.base.getSymbol(global);
494 if (sym.undf()) continue; // import, skip494 if (sym.undf()) continue; // import, skip
495 if (sym.n_desc == MachO.N_DESC_GCED) continue; // GCed, skip495 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...@@ -62,7 +62,7 @@ fn collectRoots(roots: *std.AutoHashMap(*Atom, void), macho_file: *MachO) !void
62 else => |other| {62 else => |other| {
63 assert(other == .Lib);63 assert(other == .Lib);
64 // Add exports as GC roots64 // Add exports as GC roots
65 for (macho_file.globals.values()) |global| {65 for (macho_file.globals.items) |global| {
66 const sym = macho_file.getSymbol(global);66 const sym = macho_file.getSymbol(global);
67 if (!sym.sect()) continue;67 if (!sym.sect()) continue;
68 const atom = macho_file.getAtomForSymbol(global) orelse {68 const atom = macho_file.getAtomForSymbol(global) orelse {
...@@ -77,7 +77,7 @@ fn collectRoots(roots: *std.AutoHashMap(*Atom, void), macho_file: *MachO) !void...@@ -77,7 +77,7 @@ fn collectRoots(roots: *std.AutoHashMap(*Atom, void), macho_file: *MachO) !void
77 }77 }
7878
79 // TODO just a temp until we learn how to parse unwind records79 // 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| {
81 if (macho_file.getAtomForSymbol(global)) |atom| {81 if (macho_file.getAtomForSymbol(global)) |atom| {
82 _ = try roots.getOrPut(atom);82 _ = try roots.getOrPut(atom);
83 log.debug("adding root", .{});83 log.debug("adding root", .{});