Skip to content

Commit 5b0be0d

Browse files
authored
Merge pull request #10499 from paulsnar/paulsnar/stage1-packed-structs-cabi
stage1: Fix LLVM C ABI type resolution for small packed structs
2 parents 6630a5e + 0736d30 commit 5b0be0d

File tree

3 files changed

+126
-1
lines changed

3 files changed

+126
-1
lines changed

src/stage1/analyze.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8962,7 +8962,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
89628962
struct_type->data.structure.llvm_full_type_queue_index = SIZE_MAX;
89638963
}
89648964

8965-
if (struct_type->abi_size <= 16 && struct_type->data.structure.layout == ContainerLayoutExtern)
8965+
if (struct_type->abi_size <= 16 && (struct_type->data.structure.layout == ContainerLayoutExtern || struct_type->data.structure.layout == ContainerLayoutPacked))
89668966
resolve_llvm_c_abi_type(g, struct_type);
89678967
}
89688968

test/stage1/c_abi/cfuncs.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,24 @@ struct MedStructMixed {
7575
void zig_med_struct_mixed(struct MedStructMixed);
7676
struct MedStructMixed zig_ret_med_struct_mixed();
7777

78+
struct SmallPackedStruct {
79+
uint8_t a: 2;
80+
uint8_t b: 2;
81+
uint8_t c: 2;
82+
uint8_t d: 2;
83+
uint8_t e: 1;
84+
};
85+
86+
struct BigPackedStruct {
87+
uint64_t a: 64;
88+
uint64_t b: 64;
89+
uint64_t c: 64;
90+
uint64_t d: 64;
91+
uint8_t e: 8;
92+
};
93+
94+
//void zig_small_packed_struct(struct SmallPackedStruct); // #1481
95+
void zig_big_packed_struct(struct BigPackedStruct);
7896

7997
struct SplitStructInts {
8098
uint64_t a;
@@ -137,6 +155,16 @@ void run_c_tests(void) {
137155
zig_small_struct_ints(s);
138156
}
139157

158+
{
159+
struct BigPackedStruct s = {1, 2, 3, 4, 5};
160+
zig_big_packed_struct(s);
161+
}
162+
163+
{
164+
struct SmallPackedStruct s = {0, 1, 2, 3, 1};
165+
//zig_small_packed_struct(s);
166+
}
167+
140168
{
141169
struct SplitStructInts s = {1234, 100, 1337};
142170
zig_split_struct_ints(s);
@@ -318,6 +346,44 @@ void c_split_struct_mixed(struct SplitStructMixed x) {
318346
assert_or_panic(y.c == 1337.0f);
319347
}
320348

349+
struct SmallPackedStruct c_ret_small_packed_struct() {
350+
struct SmallPackedStruct s = {
351+
.a = 0,
352+
.b = 1,
353+
.c = 2,
354+
.d = 3,
355+
.e = 1,
356+
};
357+
return s;
358+
}
359+
360+
void c_small_packed_struct(struct SmallPackedStruct x) {
361+
assert_or_panic(x.a == 0);
362+
assert_or_panic(x.a == 1);
363+
assert_or_panic(x.a == 2);
364+
assert_or_panic(x.a == 3);
365+
assert_or_panic(x.e == 1);
366+
}
367+
368+
struct BigPackedStruct c_ret_big_packed_struct() {
369+
struct BigPackedStruct s = {
370+
.a = 1,
371+
.b = 2,
372+
.c = 3,
373+
.d = 4,
374+
.e = 5,
375+
};
376+
return s;
377+
}
378+
379+
void c_big_packed_struct(struct BigPackedStruct x) {
380+
assert_or_panic(x.a == 1);
381+
assert_or_panic(x.b == 2);
382+
assert_or_panic(x.c == 3);
383+
assert_or_panic(x.d == 4);
384+
assert_or_panic(x.e == 5);
385+
}
386+
321387
struct SplitStructMixed c_ret_split_struct_mixed() {
322388
struct SplitStructMixed s = {
323389
.a = 1234,

test/stage1/c_abi/main.zig

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,65 @@ export fn zig_small_struct_ints(x: SmallStructInts) void {
230230
expect(x.d == 4) catch @panic("test failure");
231231
}
232232

233+
const SmallPackedStruct = packed struct {
234+
a: u2,
235+
b: u2,
236+
c: u2,
237+
d: u2,
238+
e: bool,
239+
};
240+
const c_small_packed_struct: fn (SmallPackedStruct) callconv(.C) void = @compileError("TODO: #1481");
241+
extern fn c_ret_small_packed_struct() SmallPackedStruct;
242+
243+
// waiting on #1481
244+
//export fn zig_small_packed_struct(x: SmallPackedStruct) void {
245+
// expect(x.a == 0) catch @panic("test failure");
246+
// expect(x.b == 1) catch @panic("test failure");
247+
// expect(x.c == 2) catch @panic("test failure");
248+
// expect(x.d == 3) catch @panic("test failure");
249+
// expect(x.e) catch @panic("test failure");
250+
//}
251+
252+
test "C ABI small packed struct" {
253+
var s = SmallPackedStruct{ .a = 0, .b = 1, .c = 2, .d = 3, .e = true };
254+
_ = s; //c_small_packed_struct(s); // waiting on #1481
255+
var s2 = c_ret_small_packed_struct();
256+
try expect(s2.a == 0);
257+
try expect(s2.b == 1);
258+
try expect(s2.c == 2);
259+
try expect(s2.d == 3);
260+
try expect(s2.e);
261+
}
262+
263+
const BigPackedStruct = packed struct {
264+
a: u64,
265+
b: u64,
266+
c: u64,
267+
d: u64,
268+
e: u8,
269+
};
270+
extern fn c_big_packed_struct(BigPackedStruct) void;
271+
extern fn c_ret_big_packed_struct() BigPackedStruct;
272+
273+
export fn zig_big_packed_struct(x: BigPackedStruct) void {
274+
expect(x.a == 1) catch @panic("test failure");
275+
expect(x.b == 2) catch @panic("test failure");
276+
expect(x.c == 3) catch @panic("test failure");
277+
expect(x.d == 4) catch @panic("test failure");
278+
expect(x.e == 5) catch @panic("test failure");
279+
}
280+
281+
test "C ABI big packed struct" {
282+
var s = BigPackedStruct{ .a = 1, .b = 2, .c = 3, .d = 4, .e = 5 };
283+
c_big_packed_struct(s);
284+
var s2 = c_ret_big_packed_struct();
285+
try expect(s2.a == 1);
286+
try expect(s2.b == 2);
287+
try expect(s2.c == 3);
288+
try expect(s2.d == 4);
289+
try expect(s2.e == 5);
290+
}
291+
233292
const SplitStructInt = extern struct {
234293
a: u64,
235294
b: u8,

0 commit comments

Comments
 (0)