aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJacob Young <jacobly0@users.noreply.github.com>2023-10-28 15:10:27 -0400
committerJacob Young <jacobly0@users.noreply.github.com>2023-10-29 05:15:35 -0400
commitf133bcba9f75562c324cced5385356ac2e08ae43 (patch)
tree0c7682b8058e8db12beb7b5cfdd0493f78765518 /src
parent37295696ec5b1350333b88173187a3db8b199925 (diff)
downloadzig-f133bcba9f75562c324cced5385356ac2e08ae43.tar.gz
zig-f133bcba9f75562c324cced5385356ac2e08ae43.zip
x86_64: fix hazard between pic call and sysv cc
Diffstat (limited to 'src')
-rw-r--r--src/arch/x86_64/CodeGen.zig25
1 files changed, 20 insertions, 5 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig
index c6d9aebf1f..290c585095 100644
--- a/src/arch/x86_64/CodeGen.zig
+++ b/src/arch/x86_64/CodeGen.zig
@@ -9971,6 +9971,7 @@ fn genCall(self: *Self, info: union(enum) {
}),
};
const fn_info = mod.typeToFunc(fn_ty).?;
+ const resolved_cc = abi.resolveCallingConvention(fn_info.cc, self.target.*);
const ExpectedContents = extern struct {
var_args: [16][@sizeOf(Type)]u8 align(@alignOf(Type)),
@@ -10012,9 +10013,7 @@ fn genCall(self: *Self, info: union(enum) {
}
try self.spillEflagsIfOccupied();
- try self.spillRegisters(abi.getCallerPreservedRegs(
- abi.resolveCallingConvention(fn_info.cc, self.target.*),
- ));
+ try self.spillRegisters(abi.getCallerPreservedRegs(resolved_cc));
// set stack arguments first because this can clobber registers
// also clobber spill arguments as we go
@@ -10109,8 +10108,24 @@ fn genCall(self: *Self, info: union(enum) {
const sym = elf_file.symbol(sym_index);
_ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
if (self.bin_file.options.pic) {
- try self.genSetReg(.rax, Type.usize, .{ .load_symbol = sym.esym_index });
- try self.asmRegister(.{ ._, .call }, .rax);
+ 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,
+ .{ .load_symbol = sym.esym_index },
+ );
+ try self.asmRegister(.{ ._, .call }, callee_reg);
} else {
_ = try self.addInst(.{
.tag = .call,