From e165b8b223bfaaeb5953dec9a1f03b8e0ce4ddab Mon Sep 17 00:00:00 2001 From: Cody Tapscott Date: Tue, 27 Sep 2022 19:57:43 -0700 Subject: [PATCH] stage2: Fix multiple_llvm_int parameter passing Small iteration oopsie We could really use some more comprehensive C ABI tests. --- src/codegen/llvm.zig | 18 ++++++----- test/c_abi/cfuncs.c | 52 ++++++++++++++++++++++++++++++++ test/c_abi/main.zig | 71 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+), 8 deletions(-) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 2f66c56823..1b793265da 100644 --- a/src/codegen/llvm.zig +++ b/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); } diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c index 439de8bbae..89de8ebcb6 100644 --- a/test/c_abi/cfuncs.c +++ b/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; } diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig index 1bf58d3fcf..e8e2f4861c 100644 --- a/test/c_abi/main.zig +++ b/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; }