diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig index 2c7e0e3464fe10803470ac2eae19efaa9f9ffb11..d499ef406fc67f0a7a4fe8c81390b6ad434a36a5 100644 --- a/src/codegen/x86_64/CodeGen.zig +++ b/src/codegen/x86_64/CodeGen.zig @@ -176621,10 +176621,20 @@ fn genCall(cg: *CodeGen, info: union(enum) { for (call_info.args, arg_types, args, frame_indices) |dst_arg, arg_ty, src_arg, frame_index| switch (dst_arg) { .none, .load_frame, .indirect_load_frame => {}, - .register => |dst_reg| try cg.genSetReg(registerAlias( - dst_reg, - @intCast(cg.unalignedSize(arg_ty)), - ), arg_ty, src_arg, opts), + .register => |dst_reg| switch (fn_info.cc) { + else => try cg.genSetReg(registerAlias( + dst_reg, + @intCast(cg.unalignedSize(arg_ty)), + ), arg_ty, src_arg, opts), + .x86_64_sysv, .x86_64_win => { + const promoted_ty = cg.promoteInt(arg_ty); + const promoted_unaligned_size: u32 = @intCast(cg.unalignedSize(promoted_ty)); + const dst_alias = registerAlias(dst_reg, promoted_unaligned_size); + try cg.genSetReg(dst_alias, promoted_ty, src_arg, opts); + if (promoted_ty.toIntern() != arg_ty.toIntern()) + try cg.truncateRegister(arg_ty, dst_alias); + }, + }, .register_pair, .register_triple, .register_quadruple, diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c index 2013a36f2e379137dc1d61243f6b8222f4677b57..cfd3872c94ef750e6663f6e9c4d186516c76beb7 100644 --- a/test/c_abi/cfuncs.c +++ b/test/c_abi/cfuncs.c @@ -16386,7 +16386,13 @@ void __attribute__((vectorcall)) c_vectorcall_check(int a, float b, double c, vo } #endif -#if defined(__x86_64__) && defined(_WIN64) +void c_x86_64_sysv_uint_int_uint_int(unsigned a, int b, unsigned c, int d) { + assert_or_panic(a == 1); + assert_or_panic(b == -2); + assert_or_panic(c == 3); + assert_or_panic(d == -4); +} + void c_win64_varargs_u64_f64_u64_f64(uint64_t a, double b, uint64_t c, double d) { assert_or_panic(a == UINT64_C(0x3ff0000000000000)); assert_or_panic(b == 2.0); @@ -16399,4 +16405,3 @@ void c_win64_varargs_f64_u64_f64_u64(double a, uint64_t b, double c, uint64_t d) assert_or_panic(c == 7.0); assert_or_panic(d == UINT64_C(0x4020000000000000)); } -#endif diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig index f494b51818c33466614e24eb0efb398abb157779..974adf898c9fd092396d279bf34a22f050235d73 100644 --- a/test/c_abi/main.zig +++ b/test/c_abi/main.zig @@ -17448,11 +17448,19 @@ test "x86 vectorcall calling convention" { static.c_vectorcall_check(1, 2.0, 3.0, @ptrFromInt(4), 5.0, 6.0, 7.0, 8.0, 9.0, 10); } +extern fn c_x86_64_sysv_uint_int_uint_int(a: u8, b: i8, c: u16, d: i16) void; + +test "x86_64 sysv args" { + if (std.lang.CallingConvention.c != .x86_64_sysv) return error.SkipZigTest; + + c_x86_64_sysv_uint_int_uint_int(1, -2, 3, -4); +} + extern fn c_win64_varargs_u64_f64_u64_f64(...) void; extern fn c_win64_varargs_f64_u64_f64_u64(...) void; test "win64 varargs" { - if (builtin.cpu.arch != .x86_64 or builtin.os.tag != .windows) return error.SkipZigTest; + if (std.lang.CallingConvention.c != .x86_64_win) return error.SkipZigTest; const Opv = extern struct {}; c_win64_varargs_u64_f64_u64_f64(