Commit e165b8b223
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;
}