| ... | @@ -9971,6 +9971,7 @@ fn genCall(self: *Self, info: union(enum) { | ... | @@ -9971,6 +9971,7 @@ fn genCall(self: *Self, info: union(enum) { |
| 9971 | }), | 9971 | }), |
| 9972 | }; | 9972 | }; |
| 9973 | const fn_info = mod.typeToFunc(fn_ty).?; | 9973 | const fn_info = mod.typeToFunc(fn_ty).?; |
| | 9974 | const resolved_cc = abi.resolveCallingConvention(fn_info.cc, self.target.*); |
| 9974 | | 9975 | |
| 9975 | const ExpectedContents = extern struct { | 9976 | const ExpectedContents = extern struct { |
| 9976 | var_args: [16][@sizeOf(Type)]u8 align(@alignOf(Type)), | 9977 | var_args: [16][@sizeOf(Type)]u8 align(@alignOf(Type)), |
| ... | @@ -10012,9 +10013,7 @@ fn genCall(self: *Self, info: union(enum) { | ... | @@ -10012,9 +10013,7 @@ fn genCall(self: *Self, info: union(enum) { |
| 10012 | } | 10013 | } |
| 10013 | | 10014 | |
| 10014 | try self.spillEflagsIfOccupied(); | 10015 | try self.spillEflagsIfOccupied(); |
| 10015 | try self.spillRegisters(abi.getCallerPreservedRegs( | 10016 | try self.spillRegisters(abi.getCallerPreservedRegs(resolved_cc)); |
| 10016 | abi.resolveCallingConvention(fn_info.cc, self.target.*), | | |
| 10017 | )); | | |
| 10018 | | 10017 | |
| 10019 | // set stack arguments first because this can clobber registers | 10018 | // set stack arguments first because this can clobber registers |
| 10020 | // also clobber spill arguments as we go | 10019 | // also clobber spill arguments as we go |
| ... | @@ -10109,8 +10108,24 @@ fn genCall(self: *Self, info: union(enum) { | ... | @@ -10109,8 +10108,24 @@ fn genCall(self: *Self, info: union(enum) { |
| 10109 | const sym = elf_file.symbol(sym_index); | 10108 | const sym = elf_file.symbol(sym_index); |
| 10110 | _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file); | 10109 | _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file); |
| 10111 | if (self.bin_file.options.pic) { | 10110 | if (self.bin_file.options.pic) { |
| 10112 | try self.genSetReg(.rax, Type.usize, .{ .load_symbol = sym.esym_index }); | 10111 | const callee_reg: Register = switch (resolved_cc) { |
| 10113 | try self.asmRegister(.{ ._, .call }, .rax); | 10112 | .SysV => callee: { |
| | 10113 | if (!fn_info.is_var_args) break :callee .rax; |
| | 10114 | const param_regs = abi.getCAbiIntParamRegs(resolved_cc); |
| | 10115 | break :callee if (call_info.gp_count < param_regs.len) |
| | 10116 | param_regs[call_info.gp_count] |
| | 10117 | else |
| | 10118 | .r10; |
| | 10119 | }, |
| | 10120 | .Win64 => .rax, |
| | 10121 | else => unreachable, |
| | 10122 | }; |
| | 10123 | try self.genSetReg( |
| | 10124 | callee_reg, |
| | 10125 | Type.usize, |
| | 10126 | .{ .load_symbol = sym.esym_index }, |
| | 10127 | ); |
| | 10128 | try self.asmRegister(.{ ._, .call }, callee_reg); |
| 10114 | } else { | 10129 | } else { |
| 10115 | _ = try self.addInst(.{ | 10130 | _ = try self.addInst(.{ |
| 10116 | .tag = .call, | 10131 | .tag = .call, |