diff options
| author | Jacob Young <jacobly0@users.noreply.github.com> | 2023-10-28 15:10:27 -0400 |
|---|---|---|
| committer | Jacob Young <jacobly0@users.noreply.github.com> | 2023-10-29 05:15:35 -0400 |
| commit | f133bcba9f75562c324cced5385356ac2e08ae43 (patch) | |
| tree | 0c7682b8058e8db12beb7b5cfdd0493f78765518 /src | |
| parent | 37295696ec5b1350333b88173187a3db8b199925 (diff) | |
| download | zig-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.zig | 25 |
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, |
