x86_64: fix windows calling convention abi

This commit is contained in:
Jacob Young 2025-09-28 07:23:08 -04:00
parent bc4da9a907
commit d5f09f56e0
4 changed files with 5540 additions and 9763 deletions

View File

@ -12103,7 +12103,7 @@ fn firstParamSRet(fn_info: InternPool.Key.FuncType, zcu: *Zcu, target: *const st
return switch (fn_info.cc) {
.auto => returnTypeByRef(zcu, target, return_type),
.x86_64_sysv => firstParamSRetSystemV(return_type, zcu, target),
.x86_64_win => x86_64_abi.classifyWindows(return_type, zcu, target) == .memory,
.x86_64_win => x86_64_abi.classifyWindows(return_type, zcu, target, .ret) == .memory,
.x86_sysv, .x86_win => isByRef(return_type, zcu),
.x86_stdcall => !isScalar(zcu, return_type),
.wasm_mvp => wasm_c_abi.classifyType(return_type, zcu) == .indirect,
@ -12205,7 +12205,7 @@ fn lowerFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType)
fn lowerWin64FnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type {
const zcu = pt.zcu;
const return_type = Type.fromInterned(fn_info.return_type);
switch (x86_64_abi.classifyWindows(return_type, zcu, zcu.getTarget())) {
switch (x86_64_abi.classifyWindows(return_type, zcu, zcu.getTarget(), .ret)) {
.integer => {
if (isScalar(zcu, return_type)) {
return o.lowerType(pt, return_type);
@ -12476,7 +12476,7 @@ const ParamTypeIterator = struct {
fn nextWin64(it: *ParamTypeIterator, ty: Type) ?Lowering {
const zcu = it.pt.zcu;
switch (x86_64_abi.classifyWindows(ty, zcu, zcu.getTarget())) {
switch (x86_64_abi.classifyWindows(ty, zcu, zcu.getTarget(), .arg)) {
.integer => {
if (isScalar(zcu, ty)) {
it.zig_index += 1;

File diff suppressed because it is too large Load Diff

View File

@ -110,7 +110,9 @@ pub const Class = enum {
}
};
pub fn classifyWindows(ty: Type, zcu: *Zcu, target: *const std.Target) Class {
pub const Context = enum { ret, arg, other };
pub fn classifyWindows(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Context) Class {
// https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-2017
// "There's a strict one-to-one correspondence between a function call's arguments
// and the registers used for those arguments. Any argument that doesn't fit in 8
@ -148,8 +150,9 @@ pub fn classifyWindows(ty: Type, zcu: *Zcu, target: *const std.Target) Class {
},
.float => switch (ty.floatBits(target)) {
16, 32, 64, 128 => .sse,
16, 32, 64 => .sse,
80 => .memory,
128 => if (ctx == .arg) .memory else .sse,
else => unreachable,
},
.vector => .sse,
@ -166,8 +169,6 @@ pub fn classifyWindows(ty: Type, zcu: *Zcu, target: *const std.Target) Class {
};
}
pub const Context = enum { ret, arg, other };
/// There are a maximum of 8 possible return slots. Returned values are in
/// the beginning of the array; unused slots are filled with .none.
pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Context) [8]Class {

View File

@ -5172,15 +5172,6 @@ test mulSaturate {
try test_mul_saturate.testIntVectors();
}
inline fn multiply(comptime Type: type, lhs: Type, rhs: Type) Type {
return lhs * rhs;
}
test multiply {
const test_multiply = binary(multiply, .{});
try test_multiply.testFloats();
try test_multiply.testFloatVectors();
}
inline fn divide(comptime Type: type, lhs: Type, rhs: Type) Type {
return lhs / rhs;
}
@ -5264,7 +5255,7 @@ inline fn mod(comptime Type: type, lhs: Type, rhs: Type) Type {
return @mod(lhs, rhs);
}
test mod {
if (@import("builtin").object_format == .coff) return error.SkipZigTest;
if (@import("builtin").object_format == .coff and @import("builtin").target.abi != .gnu) return error.SkipZigTest;
const test_mod = binary(mod, .{});
try test_mod.testInts();
try test_mod.testIntVectors();