aboutsummaryrefslogtreecommitdiff
path: root/src/arch/x86_64/CodeGen.zig
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2024-08-13 09:56:17 +0200
committerJakub Konka <kubkon@jakubkonka.com>2024-08-13 13:30:24 +0200
commitd25c93a868585e4e2f5941fcff15fa49c90510e9 (patch)
tree191902004783169c5c4fadb5a50e4af5ab87793a /src/arch/x86_64/CodeGen.zig
parentffcf0478fe646569465ac509b3e60faadd9b3697 (diff)
downloadzig-d25c93a868585e4e2f5941fcff15fa49c90510e9.tar.gz
zig-d25c93a868585e4e2f5941fcff15fa49c90510e9.zip
x86_64: emit call rel32 for near calls with linker reloc
Diffstat (limited to 'src/arch/x86_64/CodeGen.zig')
-rw-r--r--src/arch/x86_64/CodeGen.zig60
1 files changed, 26 insertions, 34 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig
index f6fbc67ff1..ea4c7ae358 100644
--- a/src/arch/x86_64/CodeGen.zig
+++ b/src/arch/x86_64/CodeGen.zig
@@ -1379,14 +1379,19 @@ fn asmImmediate(self: *Self, tag: Mir.Inst.FixedTag, imm: Immediate) !void {
.ops = switch (imm) {
.signed => .i_s,
.unsigned => .i_u,
+ .reloc => .rel,
+ },
+ .data = switch (imm) {
+ .reloc => |x| .{ .reloc = x },
+ .signed, .unsigned => .{ .i = .{
+ .fixes = tag[0],
+ .i = switch (imm) {
+ .signed => |s| @bitCast(s),
+ .unsigned => |u| @intCast(u),
+ .reloc => unreachable,
+ },
+ } },
},
- .data = .{ .i = .{
- .fixes = tag[0],
- .i = switch (imm) {
- .signed => |s| @bitCast(s),
- .unsigned => |u| @intCast(u),
- },
- } },
});
}
@@ -1406,6 +1411,7 @@ fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.FixedTag, reg: Register, imm:
const ops: Mir.Inst.Ops = switch (imm) {
.signed => .ri_s,
.unsigned => |u| if (math.cast(u32, u)) |_| .ri_u else .ri64,
+ .reloc => unreachable,
};
_ = try self.addInst(.{
.tag = tag[1],
@@ -1417,6 +1423,7 @@ fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.FixedTag, reg: Register, imm:
.i = switch (imm) {
.signed => |s| @bitCast(s),
.unsigned => |u| @intCast(u),
+ .reloc => unreachable,
},
} },
.ri64 => .{ .rx = .{
@@ -1488,6 +1495,7 @@ fn asmRegisterRegisterRegisterImmediate(
.i = switch (imm) {
.signed => |s| @bitCast(@as(i8, @intCast(s))),
.unsigned => |u| @intCast(u),
+ .reloc => unreachable,
},
} },
});
@@ -1505,6 +1513,7 @@ fn asmRegisterRegisterImmediate(
.ops = switch (imm) {
.signed => .rri_s,
.unsigned => .rri_u,
+ .reloc => unreachable,
},
.data = .{ .rri = .{
.fixes = tag[0],
@@ -1513,6 +1522,7 @@ fn asmRegisterRegisterImmediate(
.i = switch (imm) {
.signed => |s| @bitCast(s),
.unsigned => |u| @intCast(u),
+ .reloc => unreachable,
},
} },
});
@@ -1610,6 +1620,7 @@ fn asmRegisterMemoryImmediate(
if (switch (imm) {
.signed => |s| if (math.cast(i16, s)) |x| @as(u16, @bitCast(x)) else null,
.unsigned => |u| math.cast(u16, u),
+ .reloc => unreachable,
}) |small_imm| {
_ = try self.addInst(.{
.tag = tag[1],
@@ -1625,6 +1636,7 @@ fn asmRegisterMemoryImmediate(
const payload = try self.addExtra(Mir.Imm32{ .imm = switch (imm) {
.signed => |s| @bitCast(s),
.unsigned => unreachable,
+ .reloc => unreachable,
} });
assert(payload + 1 == try self.addExtra(Mir.Memory.encode(m)));
_ = try self.addInst(.{
@@ -1632,6 +1644,7 @@ fn asmRegisterMemoryImmediate(
.ops = switch (imm) {
.signed => .rmi_s,
.unsigned => .rmi_u,
+ .reloc => unreachable,
},
.data = .{ .rx = .{
.fixes = tag[0],
@@ -1679,6 +1692,7 @@ fn asmMemoryImmediate(self: *Self, tag: Mir.Inst.FixedTag, m: Memory, imm: Immed
const payload = try self.addExtra(Mir.Imm32{ .imm = switch (imm) {
.signed => |s| @bitCast(s),
.unsigned => |u| @intCast(u),
+ .reloc => unreachable,
} });
assert(payload + 1 == try self.addExtra(Mir.Memory.encode(m)));
_ = try self.addInst(.{
@@ -1686,6 +1700,7 @@ fn asmMemoryImmediate(self: *Self, tag: Mir.Inst.FixedTag, m: Memory, imm: Immed
.ops = switch (imm) {
.signed => .mi_s,
.unsigned => .mi_u,
+ .reloc => unreachable,
},
.data = .{ .x = .{
.fixes = tag[0],
@@ -12310,33 +12325,10 @@ fn genCall(self: *Self, info: union(enum) {
if (self.bin_file.cast(.elf)) |elf_file| {
const zo = elf_file.zigObjectPtr().?;
const sym_index = try zo.getOrCreateMetadataForNav(elf_file, func.owner_nav);
- if (self.mod.pic) {
- const callee_reg: Register = switch (resolved_cc) {
- .SysV => callee: {
- if (!fn_info.is_var_args) break :callee .rax;
- const param_regs = abi.getCAbiIntParamRegs(resolved_cc);
- break :callee if (call_info.gp_count < param_regs.len)
- param_regs[call_info.gp_count]
- else
- .r10;
- },
- .Win64 => .rax,
- else => unreachable,
- };
- try self.genSetReg(
- callee_reg,
- Type.usize,
- .{ .lea_symbol = .{ .sym = sym_index } },
- .{},
- );
- try self.asmRegister(.{ ._, .call }, callee_reg);
- } else try self.asmMemory(.{ ._, .call }, .{
- .base = .{ .reloc = .{
- .atom_index = try self.owner.getSymbolIndex(self),
- .sym_index = sym_index,
- } },
- .mod = .{ .rm = .{ .size = .qword } },
- });
+ try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
+ .atom_index = try self.owner.getSymbolIndex(self),
+ .sym_index = sym_index,
+ }));
} else if (self.bin_file.cast(.coff)) |coff_file| {
const atom = try coff_file.getOrCreateAtomForNav(func.owner_nav);
const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;