authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-07 14:32:24-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-08 20:10:55-07:00
log61ed4fe07ad660f3cb4372937ccd5188ce404a44
treeb8baa621a18dfb06d86b9cd48774cc4c525a4d74
parent7c1061784b8b126633cfe84f46280f7bf72beffc

stage1: fix x86 i128 C ABI for extern structs

closes #10445

3 files changed, 76 insertions(+), 2 deletions(-)

src/stage1/analyze.cpp+11-2
...@@ -8684,14 +8684,23 @@ static Error resolve_llvm_c_abi_type(CodeGen *g, ZigType *ty) {...@@ -8684,14 +8684,23 @@ static Error resolve_llvm_c_abi_type(CodeGen *g, ZigType *ty) {
8684 if (ty->data.structure.fields[i]->offset >= 8) {8684 if (ty->data.structure.fields[i]->offset >= 8) {
8685 eightbyte_index = 1;8685 eightbyte_index = 1;
8686 }8686 }
8687 X64CABIClass field_class = type_c_abi_x86_64_class(g, ty->data.structure.fields[i]->type_entry);8687 ZigType *field_ty = ty->data.structure.fields[i]->type_entry;
8688 X64CABIClass field_class = type_c_abi_x86_64_class(g, field_ty);
86888689
8689 if (field_class == X64CABIClass_INTEGER) {8690 if (field_class == X64CABIClass_INTEGER) {
8690 type_classes[eightbyte_index] = X64CABIClass_INTEGER;8691 type_classes[eightbyte_index] = X64CABIClass_INTEGER;
8691 } else if (type_classes[eightbyte_index] == X64CABIClass_Unknown) {8692 } else if (type_classes[eightbyte_index] == X64CABIClass_Unknown) {
8692 type_classes[eightbyte_index] = field_class;8693 type_classes[eightbyte_index] = field_class;
8693 }8694 }
8694 type_sizes[eightbyte_index] += ty->data.structure.fields[i]->type_entry->abi_size;8695 if (field_ty->abi_size > 8) {
8696 assert(eightbyte_index == 0);
8697 type_sizes[0] = 8;
8698 type_sizes[1] = field_ty->abi_size - 8;
8699 type_classes[1] = type_classes[0];
8700 eightbyte_index = 1;
8701 } else {
8702 type_sizes[eightbyte_index] += field_ty->abi_size;
8703 }
8695 }8704 }
86968705
8697 LLVMTypeRef return_elem_types[] = {8706 LLVMTypeRef return_elem_types[] = {
test/stage1/c_abi/cfuncs.c+38
...@@ -11,14 +11,26 @@ static void assert_or_panic(bool ok) {...@@ -11,14 +11,26 @@ static void assert_or_panic(bool ok) {
11 }11 }
12}12}
1313
14struct i128 {
15 __int128 value;
16};
17
18struct u128 {
19 unsigned __int128 value;
20};
21
14void zig_u8(uint8_t);22void zig_u8(uint8_t);
15void zig_u16(uint16_t);23void zig_u16(uint16_t);
16void zig_u32(uint32_t);24void zig_u32(uint32_t);
17void zig_u64(uint64_t);25void zig_u64(uint64_t);
26void zig_u128(unsigned __int128);
27void zig_struct_u128(struct u128);
18void zig_i8(int8_t);28void zig_i8(int8_t);
19void zig_i16(int16_t);29void zig_i16(int16_t);
20void zig_i32(int32_t);30void zig_i32(int32_t);
21void zig_i64(int64_t);31void zig_i64(int64_t);
32void zig_i128(__int128);
33void zig_struct_i128(struct i128);
22void zig_five_integers(int32_t, int32_t, int32_t, int32_t, int32_t);34void zig_five_integers(int32_t, int32_t, int32_t, int32_t, int32_t);
2335
24void zig_f32(float);36void zig_f32(float);
...@@ -130,11 +142,21 @@ void run_c_tests(void) {...@@ -130,11 +142,21 @@ void run_c_tests(void) {
130 zig_u16(0xfffe);142 zig_u16(0xfffe);
131 zig_u32(0xfffffffd);143 zig_u32(0xfffffffd);
132 zig_u64(0xfffffffffffffffc);144 zig_u64(0xfffffffffffffffc);
145 zig_u128(0xfffffffffffffffc);
146 {
147 struct u128 s = {0xfffffffffffffffc};
148 zig_struct_u128(s);
149 }
133150
134 zig_i8(-1);151 zig_i8(-1);
135 zig_i16(-2);152 zig_i16(-2);
136 zig_i32(-3);153 zig_i32(-3);
137 zig_i64(-4);154 zig_i64(-4);
155 zig_i128(-5);
156 {
157 struct i128 s = {-6};
158 zig_struct_i128(s);
159 }
138 zig_five_integers(12, 34, 56, 78, 90);160 zig_five_integers(12, 34, 56, 78, 90);
139161
140 zig_f32(12.34f);162 zig_f32(12.34f);
...@@ -221,6 +243,14 @@ void c_u64(uint64_t x) {...@@ -221,6 +243,14 @@ void c_u64(uint64_t x) {
221 assert_or_panic(x == 0xfffffffffffffffcULL);243 assert_or_panic(x == 0xfffffffffffffffcULL);
222}244}
223245
246void c_u128(unsigned __int128 x) {
247 assert_or_panic(x == 0xfffffffffffffffcULL);
248}
249
250void c_struct_u128(struct u128 x) {
251 assert_or_panic(x.value == 0xfffffffffffffffcULL);
252}
253
224void c_i8(int8_t x) {254void c_i8(int8_t x) {
225 assert_or_panic(x == -1);255 assert_or_panic(x == -1);
226}256}
...@@ -237,6 +267,14 @@ void c_i64(int64_t x) {...@@ -237,6 +267,14 @@ void c_i64(int64_t x) {
237 assert_or_panic(x == -4);267 assert_or_panic(x == -4);
238}268}
239269
270void c_i128(__int128 x) {
271 assert_or_panic(x == -5);
272}
273
274void c_struct_i128(struct i128 x) {
275 assert_or_panic(x.value == -6);
276}
277
240void c_f32(float x) {278void c_f32(float x) {
241 assert_or_panic(x == 12.34f);279 assert_or_panic(x == 12.34f);
242}280}
test/stage1/c_abi/main.zig+27
...@@ -16,10 +16,14 @@ extern fn c_u8(u8) void;...@@ -16,10 +16,14 @@ extern fn c_u8(u8) void;
16extern fn c_u16(u16) void;16extern fn c_u16(u16) void;
17extern fn c_u32(u32) void;17extern fn c_u32(u32) void;
18extern fn c_u64(u64) void;18extern fn c_u64(u64) void;
19extern fn c_u128(u128) void;
20extern fn c_struct_u128(U128) void;
19extern fn c_i8(i8) void;21extern fn c_i8(i8) void;
20extern fn c_i16(i16) void;22extern fn c_i16(i16) void;
21extern fn c_i32(i32) void;23extern fn c_i32(i32) void;
22extern fn c_i64(i64) void;24extern fn c_i64(i64) void;
25extern fn c_i128(i128) void;
26extern fn c_struct_i128(I128) void;
2327
24// On windows x64, the first 4 are passed via registers, others on the stack.28// On windows x64, the first 4 are passed via registers, others on the stack.
25extern fn c_five_integers(i32, i32, i32, i32, i32) void;29extern fn c_five_integers(i32, i32, i32, i32, i32) void;
...@@ -37,11 +41,15 @@ test "C ABI integers" {...@@ -37,11 +41,15 @@ test "C ABI integers" {
37 c_u16(0xfffe);41 c_u16(0xfffe);
38 c_u32(0xfffffffd);42 c_u32(0xfffffffd);
39 c_u64(0xfffffffffffffffc);43 c_u64(0xfffffffffffffffc);
44 c_u128(0xfffffffffffffffc);
45 c_struct_u128(.{ .value = 0xfffffffffffffffc });
4046
41 c_i8(-1);47 c_i8(-1);
42 c_i16(-2);48 c_i16(-2);
43 c_i32(-3);49 c_i32(-3);
44 c_i64(-4);50 c_i64(-4);
51 c_i128(-5);
52 c_struct_i128(.{ .value = -6 });
45 c_five_integers(12, 34, 56, 78, 90);53 c_five_integers(12, 34, 56, 78, 90);
46}54}
4755
...@@ -57,6 +65,9 @@ export fn zig_u32(x: u32) void {...@@ -57,6 +65,9 @@ export fn zig_u32(x: u32) void {
57export fn zig_u64(x: u64) void {65export fn zig_u64(x: u64) void {
58 expect(x == 0xfffffffffffffffc) catch @panic("test failure");66 expect(x == 0xfffffffffffffffc) catch @panic("test failure");
59}67}
68export fn zig_u128(x: u128) void {
69 expect(x == 0xfffffffffffffffc) catch @panic("test failure");
70}
60export fn zig_i8(x: i8) void {71export fn zig_i8(x: i8) void {
61 expect(x == -1) catch @panic("test failure");72 expect(x == -1) catch @panic("test failure");
62}73}
...@@ -69,6 +80,22 @@ export fn zig_i32(x: i32) void {...@@ -69,6 +80,22 @@ export fn zig_i32(x: i32) void {
69export fn zig_i64(x: i64) void {80export fn zig_i64(x: i64) void {
70 expect(x == -4) catch @panic("test failure");81 expect(x == -4) catch @panic("test failure");
71}82}
83export fn zig_i128(x: i128) void {
84 expect(x == -5) catch @panic("test failure");
85}
86
87const I128 = extern struct {
88 value: i128,
89};
90const U128 = extern struct {
91 value: u128,
92};
93export fn zig_struct_i128(a: I128) void {
94 expect(a.value == -6) catch @panic("test failure");
95}
96export fn zig_struct_u128(a: U128) void {
97 expect(a.value == 0xfffffffffffffffc) catch @panic("test failure");
98}
7299
73extern fn c_f32(f32) void;100extern fn c_f32(f32) void;
74extern fn c_f64(f64) void;101extern fn c_f64(f64) void;