x86_64: implement coff relocations

This commit is contained in:
Jacob Young 2025-06-09 09:05:58 -04:00 committed by mlugg
parent 746137034e
commit afa07f723f
No known key found for this signature in database
GPG Key ID: 3F5B7DCCBF4AF02E
4 changed files with 61 additions and 24 deletions

View File

@ -85269,11 +85269,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.ret => try cg.airRet(inst, false),
.ret_safe => try cg.airRet(inst, true),
.ret_load => try cg.airRetLoad(inst),
.store, .store_safe => |air_tag| if (use_old) try cg.airStore(inst, switch (air_tag) {
else => unreachable,
.store => false,
.store_safe => true,
}) else fallback: {
.store, .store_safe => |air_tag| fallback: {
const bin_op = air_datas[@intFromEnum(inst)].bin_op;
const ptr_ty = cg.typeOf(bin_op.lhs);
const ptr_info = ptr_ty.ptrInfo(zcu);

View File

@ -107,10 +107,7 @@ pub fn emitMir(emit: *Emit) Error!void {
nav,
emit.lower.target.*,
)) {
.mcv => |mcv| switch (mcv) {
else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),
.lea_symbol => |sym_index| sym_index,
},
.mcv => |mcv| mcv.lea_symbol,
.fail => |em| {
assert(emit.lower.err_msg == null);
emit.lower.err_msg = em;
@ -154,10 +151,7 @@ pub fn emitMir(emit: *Emit) Error!void {
Type.fromInterned(uav.orig_ty).ptrAlignment(emit.pt.zcu),
emit.lower.src_loc,
)) {
.mcv => |mcv| switch (mcv) {
else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),
.load_direct, .load_symbol => |sym_index| sym_index,
},
.mcv => |mcv| mcv.load_symbol,
.fail => |em| {
assert(emit.lower.err_msg == null);
emit.lower.err_msg = em;
@ -207,7 +201,9 @@ pub fn emitMir(emit: *Emit) Error!void {
switch (lowered_inst.encoding.mnemonic) {
.call => {
reloc.target.type = .branch;
try emit.encodeInst(lowered_inst, reloc_info);
if (emit.bin_file.cast(.coff)) |_| try emit.encodeInst(try .new(.none, .call, &.{
.{ .mem = .initRip(.ptr, 0) },
}, emit.lower.target), reloc_info) else try emit.encodeInst(lowered_inst, reloc_info);
continue :lowered_inst;
},
else => {},
@ -284,6 +280,37 @@ pub fn emitMir(emit: *Emit) Error!void {
}, emit.lower.target), reloc_info),
else => unreachable,
}
} else if (emit.bin_file.cast(.coff)) |_| {
if (reloc.target.is_extern) switch (lowered_inst.encoding.mnemonic) {
.lea => try emit.encodeInst(try .new(.none, .mov, &.{
lowered_inst.ops[0],
.{ .mem = .initRip(.ptr, 0) },
}, emit.lower.target), reloc_info),
.mov => {
const dst_reg = lowered_inst.ops[0].reg.to64();
try emit.encodeInst(try .new(.none, .mov, &.{
.{ .reg = dst_reg },
.{ .mem = .initRip(.ptr, 0) },
}, emit.lower.target), reloc_info);
try emit.encodeInst(try .new(.none, .mov, &.{
lowered_inst.ops[0],
.{ .mem = .initSib(lowered_inst.ops[reloc.op_index].mem.sib.ptr_size, .{ .base = .{
.reg = dst_reg,
} }) },
}, emit.lower.target), &.{});
},
else => unreachable,
} else switch (lowered_inst.encoding.mnemonic) {
.lea => try emit.encodeInst(try .new(.none, .lea, &.{
lowered_inst.ops[0],
.{ .mem = .initRip(.none, 0) },
}, emit.lower.target), reloc_info),
.mov => try emit.encodeInst(try .new(.none, .mov, &.{
lowered_inst.ops[0],
.{ .mem = .initRip(lowered_inst.ops[reloc.op_index].mem.sib.ptr_size, 0) },
}, emit.lower.target), reloc_info),
else => unreachable,
}
} else return emit.fail("TODO implement relocs for {s}", .{
@tagName(emit.bin_file.tag),
});
@ -751,6 +778,21 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI
.symbolnum = @intCast(reloc.target.index),
},
});
} else if (emit.bin_file.cast(.coff)) |coff_file| {
const atom_index = coff_file.getAtomIndexForSymbol(
.{ .sym_index = emit.atom_index, .file = null },
).?;
try coff_file.addRelocation(atom_index, .{
.type = if (reloc.target.is_extern) .got else .direct,
.target = if (reloc.target.is_extern)
coff_file.getGlobalByIndex(reloc.target.index)
else
.{ .sym_index = reloc.target.index, .file = null },
.offset = end_offset - 4,
.addend = @intCast(reloc.off),
.pcrel = true,
.length = 2,
});
} else unreachable,
.branch => if (emit.bin_file.cast(.elf)) |elf_file| {
const zo = elf_file.zigObjectPtr().?;
@ -781,13 +823,12 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI
const atom_index = coff_file.getAtomIndexForSymbol(
.{ .sym_index = emit.atom_index, .file = null },
).?;
const target: link.File.Coff.SymbolWithLoc = if (link.File.Coff.global_symbol_bit & reloc.target.index != 0)
coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & reloc.target.index)
else
.{ .sym_index = reloc.target.index, .file = null };
try coff_file.addRelocation(atom_index, .{
.type = .direct,
.target = target,
.type = if (reloc.target.is_extern) .import else .got,
.target = if (reloc.target.is_extern)
coff_file.getGlobalByIndex(reloc.target.index)
else
.{ .sym_index = reloc.target.index, .file = null },
.offset = end_offset - 4,
.addend = @intCast(reloc.off),
.pcrel = true,

View File

@ -1015,12 +1015,12 @@ pub fn genNavRef(
.internal => {
const atom_index = try coff_file.getOrCreateAtomForNav(nav_index);
const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
return .{ .mcv = .{ .load_got = sym_index } };
return .{ .mcv = .{ .lea_symbol = sym_index } };
},
.strong, .weak => {
const global_index = try coff_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));
try coff_file.need_got_table.put(zcu.gpa, global_index, {}); // needs GOT
return .{ .mcv = .{ .load_got = link.File.Coff.global_symbol_bit | global_index } };
return .{ .mcv = .{ .lea_symbol = global_index } };
},
.link_once => unreachable,
}

View File

@ -1767,7 +1767,7 @@ pub fn lowerUav(
const atom = coff.getAtom(metadata.atom);
const existing_addr = atom.getSymbol(coff).value;
if (uav_alignment.check(existing_addr))
return .{ .mcv = .{ .load_direct = atom.getSymbolIndex().? } };
return .{ .mcv = .{ .load_symbol = atom.getSymbolIndex().? } };
}
var name_buf: [32]u8 = undefined;
@ -1799,7 +1799,7 @@ pub fn lowerUav(
.section = coff.rdata_section_index.?,
});
return .{ .mcv = .{
.load_direct = coff.getAtom(atom_index).getSymbolIndex().?,
.load_symbol = coff.getAtom(atom_index).getSymbolIndex().?,
} };
}