authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-06-09 09:05:58-04:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-06-12 17:51:30+01:00
logafa07f723f956d78a4bd4c4be10ef04e86e50521
tree727dad717c38267a3ee2de671f4bffac65cf25fe
parent746137034e244d863a022b821ae0a1952d9d93c1
signaturelock-open Commit is signed but in an unrecognized format.

x86_64: implement coff relocations


4 files changed, 61 insertions(+), 24 deletions(-)

src/arch/x86_64/CodeGen.zig+1-5
...@@ -85269,11 +85269,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -85269,11 +85269,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
85269 .ret => try cg.airRet(inst, false),85269 .ret => try cg.airRet(inst, false),
85270 .ret_safe => try cg.airRet(inst, true),85270 .ret_safe => try cg.airRet(inst, true),
85271 .ret_load => try cg.airRetLoad(inst),85271 .ret_load => try cg.airRetLoad(inst),
85272 .store, .store_safe => |air_tag| if (use_old) try cg.airStore(inst, switch (air_tag) {85272 .store, .store_safe => |air_tag| fallback: {
85273 else => unreachable,
85274 .store => false,
85275 .store_safe => true,
85276 }) else fallback: {
85277 const bin_op = air_datas[@intFromEnum(inst)].bin_op;85273 const bin_op = air_datas[@intFromEnum(inst)].bin_op;
85278 const ptr_ty = cg.typeOf(bin_op.lhs);85274 const ptr_ty = cg.typeOf(bin_op.lhs);
85279 const ptr_info = ptr_ty.ptrInfo(zcu);85275 const ptr_info = ptr_ty.ptrInfo(zcu);
src/arch/x86_64/Emit.zig+56-15
...@@ -107,10 +107,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -107,10 +107,7 @@ pub fn emitMir(emit: *Emit) Error!void {
107 nav,107 nav,
108 emit.lower.target.*,108 emit.lower.target.*,
109 )) {109 )) {
110 .mcv => |mcv| switch (mcv) {110 .mcv => |mcv| mcv.lea_symbol,
111 else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),
112 .lea_symbol => |sym_index| sym_index,
113 },
114 .fail => |em| {111 .fail => |em| {
115 assert(emit.lower.err_msg == null);112 assert(emit.lower.err_msg == null);
116 emit.lower.err_msg = em;113 emit.lower.err_msg = em;
...@@ -154,10 +151,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -154,10 +151,7 @@ pub fn emitMir(emit: *Emit) Error!void {
154 Type.fromInterned(uav.orig_ty).ptrAlignment(emit.pt.zcu),151 Type.fromInterned(uav.orig_ty).ptrAlignment(emit.pt.zcu),
155 emit.lower.src_loc,152 emit.lower.src_loc,
156 )) {153 )) {
157 .mcv => |mcv| switch (mcv) {154 .mcv => |mcv| mcv.load_symbol,
158 else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),
159 .load_direct, .load_symbol => |sym_index| sym_index,
160 },
161 .fail => |em| {155 .fail => |em| {
162 assert(emit.lower.err_msg == null);156 assert(emit.lower.err_msg == null);
163 emit.lower.err_msg = em;157 emit.lower.err_msg = em;
...@@ -207,7 +201,9 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -207,7 +201,9 @@ pub fn emitMir(emit: *Emit) Error!void {
207 switch (lowered_inst.encoding.mnemonic) {201 switch (lowered_inst.encoding.mnemonic) {
208 .call => {202 .call => {
209 reloc.target.type = .branch;203 reloc.target.type = .branch;
210 try emit.encodeInst(lowered_inst, reloc_info);204 if (emit.bin_file.cast(.coff)) |_| try emit.encodeInst(try .new(.none, .call, &.{
205 .{ .mem = .initRip(.ptr, 0) },
206 }, emit.lower.target), reloc_info) else try emit.encodeInst(lowered_inst, reloc_info);
211 continue :lowered_inst;207 continue :lowered_inst;
212 },208 },
213 else => {},209 else => {},
...@@ -284,6 +280,37 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -284,6 +280,37 @@ pub fn emitMir(emit: *Emit) Error!void {
284 }, emit.lower.target), reloc_info),280 }, emit.lower.target), reloc_info),
285 else => unreachable,281 else => unreachable,
286 }282 }
283 } else if (emit.bin_file.cast(.coff)) |_| {
284 if (reloc.target.is_extern) switch (lowered_inst.encoding.mnemonic) {
285 .lea => try emit.encodeInst(try .new(.none, .mov, &.{
286 lowered_inst.ops[0],
287 .{ .mem = .initRip(.ptr, 0) },
288 }, emit.lower.target), reloc_info),
289 .mov => {
290 const dst_reg = lowered_inst.ops[0].reg.to64();
291 try emit.encodeInst(try .new(.none, .mov, &.{
292 .{ .reg = dst_reg },
293 .{ .mem = .initRip(.ptr, 0) },
294 }, emit.lower.target), reloc_info);
295 try emit.encodeInst(try .new(.none, .mov, &.{
296 lowered_inst.ops[0],
297 .{ .mem = .initSib(lowered_inst.ops[reloc.op_index].mem.sib.ptr_size, .{ .base = .{
298 .reg = dst_reg,
299 } }) },
300 }, emit.lower.target), &.{});
301 },
302 else => unreachable,
303 } else switch (lowered_inst.encoding.mnemonic) {
304 .lea => try emit.encodeInst(try .new(.none, .lea, &.{
305 lowered_inst.ops[0],
306 .{ .mem = .initRip(.none, 0) },
307 }, emit.lower.target), reloc_info),
308 .mov => try emit.encodeInst(try .new(.none, .mov, &.{
309 lowered_inst.ops[0],
310 .{ .mem = .initRip(lowered_inst.ops[reloc.op_index].mem.sib.ptr_size, 0) },
311 }, emit.lower.target), reloc_info),
312 else => unreachable,
313 }
287 } else return emit.fail("TODO implement relocs for {s}", .{314 } else return emit.fail("TODO implement relocs for {s}", .{
288 @tagName(emit.bin_file.tag),315 @tagName(emit.bin_file.tag),
289 });316 });
...@@ -751,6 +778,21 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI...@@ -751,6 +778,21 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI
751 .symbolnum = @intCast(reloc.target.index),778 .symbolnum = @intCast(reloc.target.index),
752 },779 },
753 });780 });
781 } else if (emit.bin_file.cast(.coff)) |coff_file| {
782 const atom_index = coff_file.getAtomIndexForSymbol(
783 .{ .sym_index = emit.atom_index, .file = null },
784 ).?;
785 try coff_file.addRelocation(atom_index, .{
786 .type = if (reloc.target.is_extern) .got else .direct,
787 .target = if (reloc.target.is_extern)
788 coff_file.getGlobalByIndex(reloc.target.index)
789 else
790 .{ .sym_index = reloc.target.index, .file = null },
791 .offset = end_offset - 4,
792 .addend = @intCast(reloc.off),
793 .pcrel = true,
794 .length = 2,
795 });
754 } else unreachable,796 } else unreachable,
755 .branch => if (emit.bin_file.cast(.elf)) |elf_file| {797 .branch => if (emit.bin_file.cast(.elf)) |elf_file| {
756 const zo = elf_file.zigObjectPtr().?;798 const zo = elf_file.zigObjectPtr().?;
...@@ -781,13 +823,12 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI...@@ -781,13 +823,12 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI
781 const atom_index = coff_file.getAtomIndexForSymbol(823 const atom_index = coff_file.getAtomIndexForSymbol(
782 .{ .sym_index = emit.atom_index, .file = null },824 .{ .sym_index = emit.atom_index, .file = null },
783 ).?;825 ).?;
784 const target: link.File.Coff.SymbolWithLoc = if (link.File.Coff.global_symbol_bit & reloc.target.index != 0)
785 coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & reloc.target.index)
786 else
787 .{ .sym_index = reloc.target.index, .file = null };
788 try coff_file.addRelocation(atom_index, .{826 try coff_file.addRelocation(atom_index, .{
789 .type = .direct,827 .type = if (reloc.target.is_extern) .import else .got,
790 .target = target,828 .target = if (reloc.target.is_extern)
829 coff_file.getGlobalByIndex(reloc.target.index)
830 else
831 .{ .sym_index = reloc.target.index, .file = null },
791 .offset = end_offset - 4,832 .offset = end_offset - 4,
792 .addend = @intCast(reloc.off),833 .addend = @intCast(reloc.off),
793 .pcrel = true,834 .pcrel = true,
src/codegen.zig+2-2
...@@ -1015,12 +1015,12 @@ pub fn genNavRef(...@@ -1015,12 +1015,12 @@ pub fn genNavRef(
1015 .internal => {1015 .internal => {
1016 const atom_index = try coff_file.getOrCreateAtomForNav(nav_index);1016 const atom_index = try coff_file.getOrCreateAtomForNav(nav_index);
1017 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;1017 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
1018 return .{ .mcv = .{ .load_got = sym_index } };1018 return .{ .mcv = .{ .lea_symbol = sym_index } };
1019 },1019 },
1020 .strong, .weak => {1020 .strong, .weak => {
1021 const global_index = try coff_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));1021 const global_index = try coff_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));
1022 try coff_file.need_got_table.put(zcu.gpa, global_index, {}); // needs GOT1022 try coff_file.need_got_table.put(zcu.gpa, global_index, {}); // needs GOT
1023 return .{ .mcv = .{ .load_got = link.File.Coff.global_symbol_bit | global_index } };1023 return .{ .mcv = .{ .lea_symbol = global_index } };
1024 },1024 },
1025 .link_once => unreachable,1025 .link_once => unreachable,
1026 }1026 }
src/link/Coff.zig+2-2
...@@ -1767,7 +1767,7 @@ pub fn lowerUav(...@@ -1767,7 +1767,7 @@ pub fn lowerUav(
1767 const atom = coff.getAtom(metadata.atom);1767 const atom = coff.getAtom(metadata.atom);
1768 const existing_addr = atom.getSymbol(coff).value;1768 const existing_addr = atom.getSymbol(coff).value;
1769 if (uav_alignment.check(existing_addr))1769 if (uav_alignment.check(existing_addr))
1770 return .{ .mcv = .{ .load_direct = atom.getSymbolIndex().? } };1770 return .{ .mcv = .{ .load_symbol = atom.getSymbolIndex().? } };
1771 }1771 }
17721772
1773 var name_buf: [32]u8 = undefined;1773 var name_buf: [32]u8 = undefined;
...@@ -1799,7 +1799,7 @@ pub fn lowerUav(...@@ -1799,7 +1799,7 @@ pub fn lowerUav(
1799 .section = coff.rdata_section_index.?,1799 .section = coff.rdata_section_index.?,
1800 });1800 });
1801 return .{ .mcv = .{1801 return .{ .mcv = .{
1802 .load_direct = coff.getAtom(atom_index).getSymbolIndex().?,1802 .load_symbol = coff.getAtom(atom_index).getSymbolIndex().?,
1803 } };1803 } };
1804}1804}
18051805