Commit e165b8b223

Cody Tapscott <topolarity@tapscott.me>
2022-09-28 04:57:43
stage2: Fix multiple_llvm_int parameter passing
Small iteration oopsie We could really use some more comprehensive C ABI tests.
1 parent f3a1b5c
Changed files (3)
src
codegen
test
src/codegen/llvm.zig
@@ -1035,10 +1035,11 @@ pub const Object = struct {
                     }
                     const ints_llvm_ty = dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False);
                     const casted_ptr = builder.buildBitCast(arg_ptr, ints_llvm_ty.pointerType(0), "");
-                    for (llvm_ints) |_, i_usize| {
-                        const i = @intCast(c_uint, i_usize);
-                        const param = llvm_func.getParam(i);
-                        const field_ptr = builder.buildStructGEP(ints_llvm_ty, casted_ptr, i, "");
+                    for (llvm_ints) |_, field_i_usize| {
+                        const field_i = @intCast(c_uint, field_i_usize);
+                        const param = llvm_func.getParam(llvm_arg_i);
+                        llvm_arg_i += 1;
+                        const field_ptr = builder.buildStructGEP(ints_llvm_ty, casted_ptr, field_i, "");
                         const store_inst = builder.buildStore(param, field_ptr);
                         store_inst.setAlignment(target.cpu.arch.ptrBitWidth() / 8);
                     }
@@ -1070,10 +1071,11 @@ pub const Object = struct {
                     }
                     const floats_llvm_ty = dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False);
                     const casted_ptr = builder.buildBitCast(arg_ptr, floats_llvm_ty.pointerType(0), "");
-                    for (llvm_floats) |_, i_usize| {
-                        const i = @intCast(c_uint, i_usize);
-                        const param = llvm_func.getParam(i);
-                        const field_ptr = builder.buildStructGEP(floats_llvm_ty, casted_ptr, i, "");
+                    for (llvm_floats) |_, field_i_usize| {
+                        const field_i = @intCast(c_uint, field_i_usize);
+                        const param = llvm_func.getParam(llvm_arg_i);
+                        llvm_arg_i += 1;
+                        const field_ptr = builder.buildStructGEP(floats_llvm_ty, casted_ptr, field_i, "");
                         const store_inst = builder.buildStore(param, field_ptr);
                         store_inst.setAlignment(target.cpu.arch.ptrBitWidth() / 8);
                     }
test/c_abi/cfuncs.c
@@ -120,6 +120,24 @@ typedef struct Vector5 {
     float q;
 } Vector5;
 
+typedef struct Rect {
+    uint32_t left;
+    uint32_t right;
+    uint32_t top;
+    uint32_t bottom;
+} Rect;
+
+void zig_multiple_struct_ints(struct Rect, struct Rect);
+
+typedef struct FloatRect {
+    float left;
+    float right;
+    float top;
+    float bottom;
+} FloatRect;
+
+void zig_multiple_struct_floats(struct FloatRect, struct FloatRect);
+
 void run_c_tests(void) {
     zig_u8(0xff);
     zig_u16(0xfffe);
@@ -200,6 +218,18 @@ void run_c_tests(void) {
         assert_or_panic(res.e == 24);
     }
 
+    {
+        struct Rect r1 = {1, 21, 16, 4};
+        struct Rect r2 = {178, 189, 21, 15};
+        zig_multiple_struct_ints(r1, r2);
+    }
+
+    {
+        struct FloatRect r1 = {1, 21, 16, 4};
+        struct FloatRect r2 = {178, 189, 21, 15};
+        zig_multiple_struct_floats(r1, r2);
+    }
+
     {
         assert_or_panic(zig_ret_bool() == 1);
 
@@ -436,6 +466,28 @@ void c_big_struct_floats(Vector5 vec) {
     assert_or_panic(vec.q == 55);
 }
 
+void c_multiple_struct_ints(Rect x, Rect y) {
+    assert_or_panic(x.left == 1);
+    assert_or_panic(x.right == 21);
+    assert_or_panic(x.top == 16);
+    assert_or_panic(x.bottom == 4);
+    assert_or_panic(y.left == 178);
+    assert_or_panic(y.right == 189);
+    assert_or_panic(y.top == 21);
+    assert_or_panic(y.bottom == 15);
+}
+
+void c_multiple_struct_floats(FloatRect x, FloatRect y) {
+    assert_or_panic(x.left == 1);
+    assert_or_panic(x.right == 21);
+    assert_or_panic(x.top == 16);
+    assert_or_panic(x.bottom == 4);
+    assert_or_panic(y.left == 178);
+    assert_or_panic(y.right == 189);
+    assert_or_panic(y.top == 21);
+    assert_or_panic(y.bottom == 15);
+}
+
 bool c_ret_bool() {
     return 1;
 }
test/c_abi/main.zig
@@ -355,6 +355,9 @@ export fn zig_split_struct_mixed(x: SplitStructMixed) void {
 
 extern fn c_big_struct_both(BigStruct) BigStruct;
 
+extern fn c_multiple_struct_ints(Rect, Rect) void;
+extern fn c_multiple_struct_floats(FloatRect, FloatRect) void;
+
 test "C ABI sret and byval together" {
     var s = BigStruct{
         .a = 1,
@@ -423,6 +426,74 @@ test "C ABI structs of floats as parameter" {
     c_big_struct_floats(v5);
 }
 
+const Rect = extern struct {
+    left: u32,
+    right: u32,
+    top: u32,
+    bottom: u32,
+};
+
+export fn zig_multiple_struct_ints(x: Rect, y: Rect) void {
+    expect(x.left == 1) catch @panic("test failure");
+    expect(x.right == 21) catch @panic("test failure");
+    expect(x.top == 16) catch @panic("test failure");
+    expect(x.bottom == 4) catch @panic("test failure");
+    expect(y.left == 178) catch @panic("test failure");
+    expect(y.right == 189) catch @panic("test failure");
+    expect(y.top == 21) catch @panic("test failure");
+    expect(y.bottom == 15) catch @panic("test failure");
+}
+
+test "C ABI structs of ints as multiple parameters" {
+    var r1 = Rect{
+        .left = 1,
+        .right = 21,
+        .top = 16,
+        .bottom = 4,
+    };
+    var r2 = Rect{
+        .left = 178,
+        .right = 189,
+        .top = 21,
+        .bottom = 15,
+    };
+    c_multiple_struct_ints(r1, r2);
+}
+
+const FloatRect = extern struct {
+    left: f32,
+    right: f32,
+    top: f32,
+    bottom: f32,
+};
+
+export fn zig_multiple_struct_floats(x: FloatRect, y: FloatRect) void {
+    expect(x.left == 1) catch @panic("test failure");
+    expect(x.right == 21) catch @panic("test failure");
+    expect(x.top == 16) catch @panic("test failure");
+    expect(x.bottom == 4) catch @panic("test failure");
+    expect(y.left == 178) catch @panic("test failure");
+    expect(y.right == 189) catch @panic("test failure");
+    expect(y.top == 21) catch @panic("test failure");
+    expect(y.bottom == 15) catch @panic("test failure");
+}
+
+test "C ABI structs of floats as multiple parameters" {
+    var r1 = FloatRect{
+        .left = 1,
+        .right = 21,
+        .top = 16,
+        .bottom = 4,
+    };
+    var r2 = FloatRect{
+        .left = 178,
+        .right = 189,
+        .top = 21,
+        .bottom = 15,
+    };
+    c_multiple_struct_floats(r1, r2);
+}
+
 export fn zig_ret_bool() bool {
     return true;
 }