Commit 5949851074

kcbanner <kcbanner@gmail.com>
2023-01-19 06:37:20
llvm: pass non-scalars as byref in .Stdcall
- add c_abi tests for .Stdcall - enable (x86|x86_64)-windows-gnu in the c_abi tests
1 parent d389dba
Changed files (4)
src
codegen
test
src/codegen/llvm.zig
@@ -10798,6 +10798,22 @@ const ParamTypeIterator = struct {
                     },
                 }
             },
+            .Stdcall => {
+                it.zig_index += 1;
+                it.llvm_index += 1;
+
+                if (it.target.cpu.arch != .x86 or it.target.os.tag != .windows) {
+                    return .byval;
+                }
+
+                const is_scalar = isScalar(ty);
+                if (is_scalar) {
+                    return .byval;
+                } else {
+                    it.byval_attr = true;
+                    return .byref;
+                }
+            },
             else => {
                 it.zig_index += 1;
                 it.llvm_index += 1;
test/c_abi/cfuncs.c
@@ -985,3 +985,32 @@ f128_struct c_f128_struct(f128_struct a) {
     return (f128_struct){56.78};
 }
 #endif
+
+void __attribute__((stdcall)) stdcall_scalars(char a, short b, int c, float d, double e) {
+    assert_or_panic(a == 1);
+    assert_or_panic(b == 2);
+    assert_or_panic(c == 3);
+    assert_or_panic(d == 4.0);
+    assert_or_panic(e == 5.0);
+}
+
+typedef struct {
+    short x;
+    short y;
+} Coord2;
+
+void __attribute__((stdcall)) stdcall_coord2(Coord2 a, Coord2 b, Coord2 c) {
+    assert_or_panic(a.x == 0x1111);
+    assert_or_panic(a.y == 0x2222);
+    assert_or_panic(b.x == 0x3333);
+    assert_or_panic(b.y == 0x4444);
+    assert_or_panic(c.x == 0x5555);
+    assert_or_panic(c.y == 0x6666);
+}
+
+void __attribute__((stdcall)) stdcall_big_union(union BigUnion x) {
+    assert_or_panic(x.a.a == 1);
+    assert_or_panic(x.a.b == 2);
+    assert_or_panic(x.a.c == 3);
+    assert_or_panic(x.a.d == 4);
+}
test/c_abi/main.zig
@@ -1147,3 +1147,39 @@ test "f128 struct" {
     const a = c_f128_struct(.{ .a = 12.34 });
     try expect(@floatCast(f64, a.a) == 56.78);
 }
+
+// The stdcall attribute on C functions is ignored when compiled on non-x86
+const stdcall_callconv: std.builtin.CallingConvention = if (builtin.cpu.arch == .x86) .Stdcall else .C;
+
+extern fn stdcall_scalars(i8, i16, i32, f32, f64) callconv(stdcall_callconv) void;
+test "Stdcall ABI scalars" {
+    stdcall_scalars(1, 2, 3, 4.0, 5.0);
+}
+
+const Coord2 = extern struct {
+    x: i16,
+    y: i16,
+};
+
+extern fn stdcall_coord2(Coord2, Coord2, Coord2) callconv(stdcall_callconv) void;
+test "Stdcall ABI structs" {
+    stdcall_coord2(
+        .{ .x = 0x1111, .y = 0x2222 },
+        .{ .x = 0x3333, .y = 0x4444 },
+        .{ .x = 0x5555, .y = 0x6666 },
+    );
+}
+
+extern fn stdcall_big_union(BigUnion) callconv(stdcall_callconv) void;
+test "Stdcall ABI big union" {
+    var x = BigUnion{
+        .a = BigStruct{
+            .a = 1,
+            .b = 2,
+            .c = 3,
+            .d = 4,
+            .e = 5,
+        },
+    };
+    stdcall_big_union(x);
+}
test/tests.zig
@@ -1321,6 +1321,16 @@ const c_abi_targets = [_]CrossTarget{
         .os_tag = .linux,
         .abi = .musl,
     },
+    .{
+        .cpu_arch = .x86,
+        .os_tag = .windows,
+        .abi = .gnu,
+    },
+    .{
+        .cpu_arch = .x86_64,
+        .os_tag = .windows,
+        .abi = .gnu,
+    },
 };
 
 pub fn addCAbiTests(b: *build.Builder, skip_non_native: bool, skip_release: bool) *build.Step {
@@ -1343,6 +1353,11 @@ pub fn addCAbiTests(b: *build.Builder, skip_non_native: bool, skip_release: bool
         test_step.addCSourceFile("test/c_abi/cfuncs.c", &.{"-std=c99"});
         test_step.setBuildMode(mode);
 
+        if (c_abi_target.isWindows() and c_abi_target.getCpuArch() == .x86) {
+            // LTO currently incorrectly strips stdcall name-mangled functions
+            test_step.want_lto = false;
+        }
+
         const triple_prefix = c_abi_target.zigTriple(b.allocator) catch unreachable;
         test_step.setNamePrefix(b.fmt("{s}-{s}-{s} ", .{
             "test-c-abi",