From 822c3a48197d2e5ce880fd2043e71415e04ae759 Mon Sep 17 00:00:00 2001 From: paulsnar Date: Mon, 3 Jan 2022 21:23:50 +0200 Subject: [PATCH 1/2] stage1: Resolve LLVM C ABI type for small packed structs Small packed structs weren't included in this resolution so their c_abi_type would be NULL when attempting usage later, leading to a compiler crash. Resolves #10431. --- src/stage1/analyze.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stage1/analyze.cpp b/src/stage1/analyze.cpp index 3b8d71db32..a64a6e34fb 100644 --- a/src/stage1/analyze.cpp +++ b/src/stage1/analyze.cpp @@ -8962,7 +8962,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS struct_type->data.structure.llvm_full_type_queue_index = SIZE_MAX; } - if (struct_type->abi_size <= 16 && struct_type->data.structure.layout == ContainerLayoutExtern) + if (struct_type->abi_size <= 16 && (struct_type->data.structure.layout == ContainerLayoutExtern || struct_type->data.structure.layout == ContainerLayoutPacked)) resolve_llvm_c_abi_type(g, struct_type); } From 0736d3077408ca15f1638024478f05ccce3635af Mon Sep 17 00:00:00 2001 From: paulsnar Date: Mon, 3 Jan 2022 21:25:48 +0200 Subject: [PATCH 2/2] stage1: Add tests for packed structs in C ABI --- test/stage1/c_abi/cfuncs.c | 66 ++++++++++++++++++++++++++++++++++++++ test/stage1/c_abi/main.zig | 59 ++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) diff --git a/test/stage1/c_abi/cfuncs.c b/test/stage1/c_abi/cfuncs.c index 0182462716..a2a5895ab4 100644 --- a/test/stage1/c_abi/cfuncs.c +++ b/test/stage1/c_abi/cfuncs.c @@ -75,6 +75,24 @@ struct MedStructMixed { void zig_med_struct_mixed(struct MedStructMixed); struct MedStructMixed zig_ret_med_struct_mixed(); +struct SmallPackedStruct { + uint8_t a: 2; + uint8_t b: 2; + uint8_t c: 2; + uint8_t d: 2; + uint8_t e: 1; +}; + +struct BigPackedStruct { + uint64_t a: 64; + uint64_t b: 64; + uint64_t c: 64; + uint64_t d: 64; + uint8_t e: 8; +}; + +//void zig_small_packed_struct(struct SmallPackedStruct); // #1481 +void zig_big_packed_struct(struct BigPackedStruct); struct SplitStructInts { uint64_t a; @@ -137,6 +155,16 @@ void run_c_tests(void) { zig_small_struct_ints(s); } + { + struct BigPackedStruct s = {1, 2, 3, 4, 5}; + zig_big_packed_struct(s); + } + + { + struct SmallPackedStruct s = {0, 1, 2, 3, 1}; + //zig_small_packed_struct(s); + } + { struct SplitStructInts s = {1234, 100, 1337}; zig_split_struct_ints(s); @@ -318,6 +346,44 @@ void c_split_struct_mixed(struct SplitStructMixed x) { assert_or_panic(y.c == 1337.0f); } +struct SmallPackedStruct c_ret_small_packed_struct() { + struct SmallPackedStruct s = { + .a = 0, + .b = 1, + .c = 2, + .d = 3, + .e = 1, + }; + return s; +} + +void c_small_packed_struct(struct SmallPackedStruct x) { + assert_or_panic(x.a == 0); + assert_or_panic(x.a == 1); + assert_or_panic(x.a == 2); + assert_or_panic(x.a == 3); + assert_or_panic(x.e == 1); +} + +struct BigPackedStruct c_ret_big_packed_struct() { + struct BigPackedStruct s = { + .a = 1, + .b = 2, + .c = 3, + .d = 4, + .e = 5, + }; + return s; +} + +void c_big_packed_struct(struct BigPackedStruct x) { + assert_or_panic(x.a == 1); + assert_or_panic(x.b == 2); + assert_or_panic(x.c == 3); + assert_or_panic(x.d == 4); + assert_or_panic(x.e == 5); +} + struct SplitStructMixed c_ret_split_struct_mixed() { struct SplitStructMixed s = { .a = 1234, diff --git a/test/stage1/c_abi/main.zig b/test/stage1/c_abi/main.zig index 40362a288e..abd9be4922 100644 --- a/test/stage1/c_abi/main.zig +++ b/test/stage1/c_abi/main.zig @@ -230,6 +230,65 @@ export fn zig_small_struct_ints(x: SmallStructInts) void { expect(x.d == 4) catch @panic("test failure"); } +const SmallPackedStruct = packed struct { + a: u2, + b: u2, + c: u2, + d: u2, + e: bool, +}; +const c_small_packed_struct: fn (SmallPackedStruct) callconv(.C) void = @compileError("TODO: #1481"); +extern fn c_ret_small_packed_struct() SmallPackedStruct; + +// waiting on #1481 +//export fn zig_small_packed_struct(x: SmallPackedStruct) void { +// expect(x.a == 0) catch @panic("test failure"); +// expect(x.b == 1) catch @panic("test failure"); +// expect(x.c == 2) catch @panic("test failure"); +// expect(x.d == 3) catch @panic("test failure"); +// expect(x.e) catch @panic("test failure"); +//} + +test "C ABI small packed struct" { + var s = SmallPackedStruct{ .a = 0, .b = 1, .c = 2, .d = 3, .e = true }; + _ = s; //c_small_packed_struct(s); // waiting on #1481 + var s2 = c_ret_small_packed_struct(); + try expect(s2.a == 0); + try expect(s2.b == 1); + try expect(s2.c == 2); + try expect(s2.d == 3); + try expect(s2.e); +} + +const BigPackedStruct = packed struct { + a: u64, + b: u64, + c: u64, + d: u64, + e: u8, +}; +extern fn c_big_packed_struct(BigPackedStruct) void; +extern fn c_ret_big_packed_struct() BigPackedStruct; + +export fn zig_big_packed_struct(x: BigPackedStruct) void { + expect(x.a == 1) catch @panic("test failure"); + expect(x.b == 2) catch @panic("test failure"); + expect(x.c == 3) catch @panic("test failure"); + expect(x.d == 4) catch @panic("test failure"); + expect(x.e == 5) catch @panic("test failure"); +} + +test "C ABI big packed struct" { + var s = BigPackedStruct{ .a = 1, .b = 2, .c = 3, .d = 4, .e = 5 }; + c_big_packed_struct(s); + var s2 = c_ret_big_packed_struct(); + try expect(s2.a == 1); + try expect(s2.b == 2); + try expect(s2.c == 3); + try expect(s2.d == 4); + try expect(s2.e == 5); +} + const SplitStructInt = extern struct { a: u64, b: u8,