| author | |
| committer | |
| log | 69da56b36c1bd23214b9c72587cdd424637d2ced |
| tree | 7a89fa64057fae83b41de04f4b16f16505655957 |
| parent | 5b9c5191ab919f4166a9e0c4486bd57bb2533791 |
| parent | a1b8545265b4fb47fe45287655f8885d092aa9df |
| signature |
Self-hosted backends and linkers refactor: x86_64 + aarch64 + macho + coff10 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 at | 139 | /// 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 entry | 142 | /// 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 referenced | 145 | 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 in | 148 | /// 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 x30 | 3488 | // 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 register | 4582 | .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 until | 5086 | // 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 | } |
| 167 | 161 | ||
| 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 { |
| 2691 | 2657 | ||
| 2692 | fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue) InnerError!void { | 2658 | fn 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_index | 2665 | fn_owner_decl.link.macho.sym_index |
| 2703 | else | 2666 | 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 *%rax | 4067 | // 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(); |
| 5960 | 5893 | ||
| 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 | } |
| 5993 | 5922 | ||
| 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(); |
| 6121 | 6046 | ||
| 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 | } |
| 1172 | 1175 |
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); |
| 1425 | 1425 | ||
| 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 | } |
| 1436 | 1434 | ||
| 1437 | log.debug("TODO finish resolveGlobalSymbols implementation", .{}); | 1435 | log.debug("TODO finish resolveGlobalSymbols implementation", .{}); |
| 1438 | 1436 | ||
| 1439 | if (sym.section_number == .UNDEFINED) return; | 1437 | if (sym.section_number == .UNDEFINED) return; |
| 1440 | 1438 | ||
| 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 | } |
| 1444 | 1443 | ||
| 1445 | pub fn flush(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !void { | 1444 | pub 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 | } |
| 1545 | 1544 | ||
| 1546 | pub fn getGlobalSymbol(self: *Coff, name: []const u8) !u32 { | 1545 | pub 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 | } |
| 1550 | 1552 | ||
| 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; |
| 1556 | 1556 | ||
| 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; |
| 1561 | 1562 | ||
| 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); |
| 1564 | 1564 | ||
| 1565 | return sym_index; | 1565 | return global_index; |
| 1566 | } | 1566 | } |
| 1567 | 1567 | ||
| 1568 | pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl: *Module.Decl) !void { | 1568 | pub 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 | } |
| 2063 | 2063 | ||
| 2064 | /// Returns pointer to the global entry for `name` if one exists. | ||
| 2065 | pub 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. | ||
| 2071 | pub 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. | ||
| 2077 | pub fn getGlobalIndex(self: *const Coff, name: []const u8) ?u32 { | ||
| 2078 | return self.resolver.get(name); | ||
| 2079 | } | ||
| 2080 | |||
| 2081 | /// Returns global entry at `index`. | ||
| 2082 | pub fn getGlobalByIndex(self: *const Coff, index: u32) SymbolWithLoc { | ||
| 2083 | assert(index < self.globals.items.len); | ||
| 2084 | return self.globals.items[index]; | ||
| 2085 | } | ||
| 2086 | |||
| 2087 | const 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. | ||
| 2095 | pub 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. |
| 2066 | pub fn getAtomForSymbol(self: *Coff, sym_loc: SymbolWithLoc) ?*Atom { | 2109 | pub 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 | |||
| 115 | pub 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, |
| 131 | data_section_index: ?u8 = null, | 131 | data_section_index: ?u8 = null, |
| 132 | 132 | ||
| 133 | locals: std.ArrayListUnmanaged(macho.nlist_64) = .{}, | 133 | locals: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 134 | globals: std.StringArrayHashMapUnmanaged(SymbolWithLoc) = .{}, | 134 | globals: std.ArrayListUnmanaged(SymbolWithLoc) = .{}, |
| 135 | // FIXME Jakub | 135 | resolver: 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. | ||
| 142 | unresolved: std.AutoArrayHashMapUnmanaged(u32, bool) = .{}, | 136 | unresolved: std.AutoArrayHashMapUnmanaged(u32, bool) = .{}, |
| 143 | 137 | ||
| 144 | locals_free_list: std.ArrayListUnmanaged(u32) = .{}, | 138 | locals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 139 | globals_free_list: std.ArrayListUnmanaged(u32) = .{}, | ||
| 145 | 140 | ||
| 146 | dyld_stub_binder_index: ?u32 = null, | 141 | dyld_stub_binder_index: ?u32 = null, |
| 147 | dyld_private_atom: ?*Atom = null, | 142 | dyld_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 { |
| 2048 | 2043 | ||
| 2049 | pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !*Atom { | 2044 | pub 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 { |
| 2074 | 2064 | ||
| 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 { |
| 2093 | 2083 | ||
| 2094 | pub fn createTlvPtrAtom(self: *MachO, target: SymbolWithLoc) !*Atom { | 2084 | pub 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()); |
| 2108 | 2093 | ||
| 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; |
| 2131 | 2116 | ||
| 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; |
| 2143 | 2123 | ||
| 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); |
| 2301 | 2273 | ||
| 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 { |
| 2352 | 2324 | ||
| 2353 | pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, target: SymbolWithLoc) !*Atom { | 2325 | pub 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); |
| 2378 | 2346 | ||
| 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 type | 2372 | 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 | // jmp | 2381 | // 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 { |
| 2472 | fn createTentativeDefAtoms(self: *MachO) !void { | 2436 | fn createTentativeDefAtoms(self: *MachO) !void { |
| 2473 | const gpa = self.base.allocator; | 2437 | const gpa = self.base.allocator; |
| 2474 | 2438 | ||
| 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; |
| 2478 | 2442 | ||
| ... | @@ -2516,51 +2480,44 @@ fn createTentativeDefAtoms(self: *MachO) !void { | ... | @@ -2516,51 +2480,44 @@ fn createTentativeDefAtoms(self: *MachO) !void { |
| 2516 | 2480 | ||
| 2517 | fn createMhExecuteHeaderSymbol(self: *MachO) !void { | 2481 | fn 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 | } |
| 2523 | 2487 | ||
| 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 | } |
| 2543 | 2503 | ||
| 2544 | fn createDsoHandleSymbol(self: *MachO) !void { | 2504 | fn 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; | ||
| 2548 | 2507 | ||
| 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 | } |
| 2565 | 2522 | ||
| 2566 | fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void { | 2523 | fn 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); |
| 2570 | 2527 | ||
| 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); |
| 2586 | 2538 | ||
| ... | @@ -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; |
| 2621 | 2573 | ||
| 2622 | _ = self.unresolved.swapRemove(@intCast(u32, self.globals.getIndex(name).?)); | 2574 | _ = self.unresolved.swapRemove(self.getGlobalIndex(sym_name).?); |
| 2623 | 2575 | ||
| 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); |
| 2689 | 2642 | ||
| 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 { |
| 2710 | fn resolveSymbolsInDylibs(self: *MachO) !void { | 2663 | fn resolveSymbolsInDylibs(self: *MachO) !void { |
| 2711 | if (self.dylibs.items.len == 0) return; | 2664 | if (self.dylibs.items.len == 0) return; |
| 2712 | 2665 | ||
| 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); |
| 2719 | 2673 | ||
| ... | @@ -2722,7 +2676,7 @@ fn resolveSymbolsInDylibs(self: *MachO) !void { | ... | @@ -2722,7 +2676,7 @@ fn resolveSymbolsInDylibs(self: *MachO) !void { |
| 2722 | 2676 | ||
| 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 | } |
| 2727 | 2681 | ||
| 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); |
| 2766 | 2720 | ||
| ... | @@ -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 imports | 2754 | if (self.unresolved.count() == 0) return; // no need for a stub binder if we don't have any imports |
| 2801 | 2755 | ||
| 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]; | ||
| 2816 | 2771 | ||
| 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; |
| 2819 | 2774 | ||
| 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 | } |
| 2824 | 2779 | ||
| 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); |
| 3056 | 3014 | ||
| 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); | ||
| 3061 | 3022 | ||
| 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 | } |
| 3213 | 3174 | ||
| 3175 | fn 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 | |||
| 3214 | pub fn allocateGotEntry(self: *MachO, target: SymbolWithLoc) !u32 { | 3198 | pub 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( |
| 3832 | 3816 | ||
| 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 {}; |
| 3871 | 3855 | ||
| 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 | } |
| 3879 | 3865 | ||
| ... | @@ -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 { |
| 4864 | 4850 | ||
| 4865 | pub fn getGlobalSymbol(self: *MachO, name: []const u8) !u32 { | 4851 | pub 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).?; |
| 4871 | 4858 | ||
| 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 | } |
| 4877 | 4862 | ||
| 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); |
| 4891 | 4871 | ||
| 4892 | return sym_index; | 4872 | return global_index; |
| 4893 | } | 4873 | } |
| 4894 | 4874 | ||
| 4895 | fn getSegmentAllocBase(self: MachO, indices: []const ?u8) struct { vmaddr: u64, fileoff: u64 } { | 4875 | fn 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); |
| 5073 | 5053 | ||
| 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 first | 5251 | // 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); |
| 5275 | 5255 | ||
| 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, skip | 5433 | 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, skip | 5435 | if (self.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip |
| 5456 | if (self.globals.contains(self.getSymbolName(sym_loc))) continue; // global symbol is either an export or import, skip | 5436 | if (self.getGlobal(self.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip |
| 5457 | try locals.append(sym); | 5437 | try locals.append(sym); |
| 5458 | } | 5438 | } |
| 5459 | 5439 | ||
| ... | @@ -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, skip | 5443 | 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, skip | 5445 | if (self.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip |
| 5466 | if (self.globals.contains(self.getSymbolName(sym_loc))) continue; // global symbol is either an export or import, skip | 5446 | if (self.getGlobal(self.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip |
| 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(); |
| 5479 | 5459 | ||
| 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, skip | 5462 | if (sym.undf()) continue; // import, skip |
| 5483 | if (sym.n_desc == N_DESC_GCED) continue; // GCed, skip | 5463 | 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 { |
| 5491 | 5471 | ||
| 5492 | var imports_table = std.AutoHashMap(SymbolWithLoc, u32).init(gpa); | 5472 | var imports_table = std.AutoHashMap(SymbolWithLoc, u32).init(gpa); |
| 5493 | 5473 | ||
| 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, skip | 5476 | if (sym.n_strx == 0) continue; // no name, skip |
| 5497 | if (!sym.undf()) continue; // not an import, skip | 5477 | 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 | } |
| 5800 | 5780 | ||
| 5781 | /// Returns pointer to the global entry for `name` if one exists. | ||
| 5782 | pub 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. | ||
| 5788 | pub 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. | ||
| 5794 | pub fn getGlobalIndex(self: *const MachO, name: []const u8) ?u32 { | ||
| 5795 | return self.resolver.get(name); | ||
| 5796 | } | ||
| 5797 | |||
| 5798 | /// Returns global entry at `index`. | ||
| 5799 | pub fn getGlobalByIndex(self: *const MachO, index: u32) SymbolWithLoc { | ||
| 5800 | assert(index < self.globals.items.len); | ||
| 5801 | return self.globals.items[index]; | ||
| 5802 | } | ||
| 5803 | |||
| 5804 | const 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. | ||
| 5812 | pub 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. |
| 5803 | pub fn getAtomForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?*Atom { | 5826 | pub 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. |
| 5835 | pub fn getEntryPoint(self: MachO) error{MissingMainEntrypoint}!SymbolWithLoc { | 5858 | pub 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 | } |
| 6343 | 6366 | ||
| 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 | } |
| 6349 | 6372 | ||
| 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-less | 579 | // 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, skip | 480 | 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, skip | 482 | if (self.base.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip |
| 483 | if (self.base.globals.contains(self.base.getSymbolName(sym_loc))) continue; // global symbol is either an export or import, skip | 483 | if (self.base.getGlobal(self.base.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip |
| 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(); |
| 491 | 491 | ||
| 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, skip | 494 | if (sym.undf()) continue; // import, skip |
| 495 | if (sym.n_desc == MachO.N_DESC_GCED) continue; // GCed, skip | 495 | 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 roots | 64 | // 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 | } |
| 78 | 78 | ||
| 79 | // TODO just a temp until we learn how to parse unwind records | 79 | // 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", .{}); |