authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-09 13:23:20-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-02-09 13:23:20-05:00
logdb56d74a3bc9c6240d24838753a7042ba91501a1
treed5205539c16c3c22e31b18c5cb01efb929b6f308
parent92cb17a331b0f2f3a89b8e5e6995e8e36b9f3679
parent77a6031edbd17dfdf654f24d139f27ac7adeb82f
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10834 from ziglang/fix-x86-i128-c-abi

stage1: fix x86 i128 C ABI for extern structs

5 files changed, 166 insertions(+), 51 deletions(-)

src/arch/x86_64/abi.zig+27-3
...@@ -18,10 +18,34 @@ pub fn classifyWindows(ty: Type, target: Target) Class {...@@ -18,10 +18,34 @@ pub fn classifyWindows(ty: Type, target: Target) Class {
18 else => return .memory,18 else => return .memory,
19 }19 }
20 return switch (ty.zigTypeTag()) {20 return switch (ty.zigTypeTag()) {
21 .Int, .Bool, .Enum, .Void, .NoReturn, .ErrorSet, .Struct, .Union => .integer,21 .Pointer,
22 .Optional => if (ty.isPtrLikeOptional()) return .integer else return .memory,22 .Int,
23 .Bool,
24 .Enum,
25 .Void,
26 .NoReturn,
27 .ErrorSet,
28 .Struct,
29 .Union,
30 .Optional,
31 .Array,
32 .ErrorUnion,
33 .AnyFrame,
34 .Frame,
35 => .integer,
36
23 .Float, .Vector => .sse,37 .Float, .Vector => .sse,
24 else => unreachable,38
39 .Type,
40 .ComptimeFloat,
41 .ComptimeInt,
42 .Undefined,
43 .Null,
44 .BoundFn,
45 .Fn,
46 .Opaque,
47 .EnumLiteral,
48 => unreachable,
25 };49 };
26}50}
2751
src/stage1/analyze.cpp+61-16
...@@ -8279,23 +8279,53 @@ Error file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents_buf) {...@@ -8279,23 +8279,53 @@ Error file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents_buf) {
82798279
8280static X64CABIClass type_windows_abi_x86_64_class(CodeGen *g, ZigType *ty, size_t ty_size) {8280static X64CABIClass type_windows_abi_x86_64_class(CodeGen *g, ZigType *ty, size_t ty_size) {
8281 // https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-20178281 // https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-2017
8282 switch (ty_size) {
8283 case 1:
8284 case 2:
8285 case 4:
8286 case 8:
8287 break;
8288 case 16:
8289 return (ty->id == ZigTypeIdVector) ? X64CABIClass_SSE : X64CABIClass_MEMORY;
8290 default:
8291 return X64CABIClass_MEMORY;
8292 }
8282 switch (ty->id) {8293 switch (ty->id) {
8283 case ZigTypeIdEnum:8294 case ZigTypeIdInvalid:
8295 case ZigTypeIdMetaType:
8296 case ZigTypeIdComptimeFloat:
8297 case ZigTypeIdComptimeInt:
8298 case ZigTypeIdNull:
8299 case ZigTypeIdUndefined:
8300 case ZigTypeIdBoundFn:
8301 case ZigTypeIdOpaque:
8302 case ZigTypeIdEnumLiteral:
8303 zig_unreachable();
8304
8305 case ZigTypeIdFn:
8306 case ZigTypeIdPointer:
8284 case ZigTypeIdInt:8307 case ZigTypeIdInt:
8285 case ZigTypeIdBool:8308 case ZigTypeIdBool:
8309 case ZigTypeIdEnum:
8310 case ZigTypeIdVoid:
8311 case ZigTypeIdUnreachable:
8312 case ZigTypeIdErrorSet:
8313 case ZigTypeIdErrorUnion:
8314 case ZigTypeIdStruct:
8315 case ZigTypeIdUnion:
8316 case ZigTypeIdOptional:
8317 case ZigTypeIdFnFrame:
8318 case ZigTypeIdAnyFrame:
8286 return X64CABIClass_INTEGER;8319 return X64CABIClass_INTEGER;
8320
8287 case ZigTypeIdFloat:8321 case ZigTypeIdFloat:
8288 case ZigTypeIdVector:8322 case ZigTypeIdVector:
8289 return X64CABIClass_SSE;8323 return X64CABIClass_SSE;
8290 case ZigTypeIdStruct:8324
8291 case ZigTypeIdUnion: {8325 case ZigTypeIdArray:
8292 if (ty_size <= 8)
8293 return X64CABIClass_INTEGER;
8294 return X64CABIClass_MEMORY;
8295 }
8296 default:
8297 return X64CABIClass_Unknown;8326 return X64CABIClass_Unknown;
8298 }8327 }
8328 zig_unreachable();
8299}8329}
83008330
8301static X64CABIClass type_system_V_abi_x86_64_class(CodeGen *g, ZigType *ty, size_t ty_size) {8331static X64CABIClass type_system_V_abi_x86_64_class(CodeGen *g, ZigType *ty, size_t ty_size) {
...@@ -8374,17 +8404,19 @@ static X64CABIClass type_system_V_abi_x86_64_class(CodeGen *g, ZigType *ty, size...@@ -8374,17 +8404,19 @@ static X64CABIClass type_system_V_abi_x86_64_class(CodeGen *g, ZigType *ty, size
83748404
8375X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) {8405X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) {
8376 Error err;8406 Error err;
8377
8378 const size_t ty_size = type_size(g, ty);8407 const size_t ty_size = type_size(g, ty);
8408
8409 if (g->zig_target->os == OsWindows || g->zig_target->os == OsUefi) {
8410 return type_windows_abi_x86_64_class(g, ty, ty_size);
8411 }
8412
8379 ZigType *ptr_type;8413 ZigType *ptr_type;
8380 if ((err = get_codegen_ptr_type(g, ty, &ptr_type))) return X64CABIClass_Unknown;8414 if ((err = get_codegen_ptr_type(g, ty, &ptr_type))) return X64CABIClass_Unknown;
8381 if (ptr_type != nullptr)8415 if (ptr_type != nullptr)
8382 return X64CABIClass_INTEGER;8416 return X64CABIClass_INTEGER;
83838417
8384 if (g->zig_target->os == OsWindows || g->zig_target->os == OsUefi) {8418 if (g->zig_target->arch == ZigLLVM_aarch64 ||
8385 return type_windows_abi_x86_64_class(g, ty, ty_size);8419 g->zig_target->arch == ZigLLVM_aarch64_be)
8386 } else if (g->zig_target->arch == ZigLLVM_aarch64 ||
8387 g->zig_target->arch == ZigLLVM_aarch64_be)
8388 {8420 {
8389 X64CABIClass result = type_system_V_abi_x86_64_class(g, ty, ty_size);8421 X64CABIClass result = type_system_V_abi_x86_64_class(g, ty, ty_size);
8390 return (result == X64CABIClass_MEMORY) ? X64CABIClass_MEMORY_nobyval : result;8422 return (result == X64CABIClass_MEMORY) ? X64CABIClass_MEMORY_nobyval : result;
...@@ -8684,14 +8716,23 @@ static Error resolve_llvm_c_abi_type(CodeGen *g, ZigType *ty) {...@@ -8684,14 +8716,23 @@ static Error resolve_llvm_c_abi_type(CodeGen *g, ZigType *ty) {
8684 if (ty->data.structure.fields[i]->offset >= 8) {8716 if (ty->data.structure.fields[i]->offset >= 8) {
8685 eightbyte_index = 1;8717 eightbyte_index = 1;
8686 }8718 }
8687 X64CABIClass field_class = type_c_abi_x86_64_class(g, ty->data.structure.fields[i]->type_entry);8719 ZigType *field_ty = ty->data.structure.fields[i]->type_entry;
8720 X64CABIClass field_class = type_c_abi_x86_64_class(g, field_ty);
86888721
8689 if (field_class == X64CABIClass_INTEGER) {8722 if (field_class == X64CABIClass_INTEGER) {
8690 type_classes[eightbyte_index] = X64CABIClass_INTEGER;8723 type_classes[eightbyte_index] = X64CABIClass_INTEGER;
8691 } else if (type_classes[eightbyte_index] == X64CABIClass_Unknown) {8724 } else if (type_classes[eightbyte_index] == X64CABIClass_Unknown) {
8692 type_classes[eightbyte_index] = field_class;8725 type_classes[eightbyte_index] = field_class;
8693 }8726 }
8694 type_sizes[eightbyte_index] += ty->data.structure.fields[i]->type_entry->abi_size;8727 if (field_ty->abi_size > 8) {
8728 assert(eightbyte_index == 0);
8729 type_sizes[0] = 8;
8730 type_sizes[1] = field_ty->abi_size - 8;
8731 type_classes[1] = type_classes[0];
8732 eightbyte_index = 1;
8733 } else {
8734 type_sizes[eightbyte_index] += field_ty->abi_size;
8735 }
8695 }8736 }
86968737
8697 LLVMTypeRef return_elem_types[] = {8738 LLVMTypeRef return_elem_types[] = {
...@@ -8980,8 +9021,12 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS...@@ -8980,8 +9021,12 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
8980 struct_type->data.structure.llvm_full_type_queue_index = SIZE_MAX;9021 struct_type->data.structure.llvm_full_type_queue_index = SIZE_MAX;
8981 }9022 }
89829023
8983 if (struct_type->abi_size <= 16 && (struct_type->data.structure.layout == ContainerLayoutExtern || struct_type->data.structure.layout == ContainerLayoutPacked))9024 if (struct_type->abi_size <= 16 &&
9025 (struct_type->data.structure.layout == ContainerLayoutExtern ||
9026 struct_type->data.structure.layout == ContainerLayoutPacked))
9027 {
8984 resolve_llvm_c_abi_type(g, struct_type);9028 resolve_llvm_c_abi_type(g, struct_type);
9029 }
8985}9030}
89869031
8987// This is to be used instead of void for debug info types, to avoid tripping9032// This is to be used instead of void for debug info types, to avoid tripping
test/stage1/c_abi/build.zig+3
...@@ -2,15 +2,18 @@ const Builder = @import("std").build.Builder;...@@ -2,15 +2,18 @@ const Builder = @import("std").build.Builder;
22
3pub fn build(b: *Builder) void {3pub fn build(b: *Builder) void {
4 const rel_opts = b.standardReleaseOptions();4 const rel_opts = b.standardReleaseOptions();
5 const target = b.standardTargetOptions(.{});
56
6 const c_obj = b.addObject("cfuncs", null);7 const c_obj = b.addObject("cfuncs", null);
7 c_obj.addCSourceFile("cfuncs.c", &[_][]const u8{"-std=c99"});8 c_obj.addCSourceFile("cfuncs.c", &[_][]const u8{"-std=c99"});
8 c_obj.setBuildMode(rel_opts);9 c_obj.setBuildMode(rel_opts);
9 c_obj.linkSystemLibrary("c");10 c_obj.linkSystemLibrary("c");
11 c_obj.target = target;
1012
11 const main = b.addTest("main.zig");13 const main = b.addTest("main.zig");
12 main.setBuildMode(rel_opts);14 main.setBuildMode(rel_opts);
13 main.addObject(c_obj);15 main.addObject(c_obj);
16 main.target = target;
1417
15 const test_step = b.step("test", "Test the program");18 const test_step = b.step("test", "Test the program");
16 test_step.dependOn(&main.step);19 test_step.dependOn(&main.step);
test/stage1/c_abi/cfuncs.c+26
...@@ -11,14 +11,24 @@ static void assert_or_panic(bool ok) {...@@ -11,14 +11,24 @@ 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_struct_u128(struct u128);
18void zig_i8(int8_t);27void zig_i8(int8_t);
19void zig_i16(int16_t);28void zig_i16(int16_t);
20void zig_i32(int32_t);29void zig_i32(int32_t);
21void zig_i64(int64_t);30void zig_i64(int64_t);
31void zig_struct_i128(struct i128);
22void zig_five_integers(int32_t, int32_t, int32_t, int32_t, int32_t);32void zig_five_integers(int32_t, int32_t, int32_t, int32_t, int32_t);
2333
24void zig_f32(float);34void zig_f32(float);
...@@ -130,11 +140,19 @@ void run_c_tests(void) {...@@ -130,11 +140,19 @@ void run_c_tests(void) {
130 zig_u16(0xfffe);140 zig_u16(0xfffe);
131 zig_u32(0xfffffffd);141 zig_u32(0xfffffffd);
132 zig_u64(0xfffffffffffffffc);142 zig_u64(0xfffffffffffffffc);
143 {
144 struct u128 s = {0xfffffffffffffffc};
145 zig_struct_u128(s);
146 }
133147
134 zig_i8(-1);148 zig_i8(-1);
135 zig_i16(-2);149 zig_i16(-2);
136 zig_i32(-3);150 zig_i32(-3);
137 zig_i64(-4);151 zig_i64(-4);
152 {
153 struct i128 s = {-6};
154 zig_struct_i128(s);
155 }
138 zig_five_integers(12, 34, 56, 78, 90);156 zig_five_integers(12, 34, 56, 78, 90);
139157
140 zig_f32(12.34f);158 zig_f32(12.34f);
...@@ -221,6 +239,10 @@ void c_u64(uint64_t x) {...@@ -221,6 +239,10 @@ void c_u64(uint64_t x) {
221 assert_or_panic(x == 0xfffffffffffffffcULL);239 assert_or_panic(x == 0xfffffffffffffffcULL);
222}240}
223241
242void c_struct_u128(struct u128 x) {
243 assert_or_panic(x.value == 0xfffffffffffffffcULL);
244}
245
224void c_i8(int8_t x) {246void c_i8(int8_t x) {
225 assert_or_panic(x == -1);247 assert_or_panic(x == -1);
226}248}
...@@ -237,6 +259,10 @@ void c_i64(int64_t x) {...@@ -237,6 +259,10 @@ void c_i64(int64_t x) {
237 assert_or_panic(x == -4);259 assert_or_panic(x == -4);
238}260}
239261
262void c_struct_i128(struct i128 x) {
263 assert_or_panic(x.value == -6);
264}
265
240void c_f32(float x) {266void c_f32(float x) {
241 assert_or_panic(x == 12.34f);267 assert_or_panic(x == 12.34f);
242}268}
test/stage1/c_abi/main.zig+49-32
...@@ -16,20 +16,22 @@ extern fn c_u8(u8) void;...@@ -16,20 +16,22 @@ 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_struct_u128(U128) void;
19extern fn c_i8(i8) void;20extern fn c_i8(i8) void;
20extern fn c_i16(i16) void;21extern fn c_i16(i16) void;
21extern fn c_i32(i32) void;22extern fn c_i32(i32) void;
22extern fn c_i64(i64) void;23extern fn c_i64(i64) void;
24extern fn c_struct_i128(I128) void;
2325
24// On windows x64, the first 4 are passed via registers, others on the stack.26// 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;27extern fn c_five_integers(i32, i32, i32, i32, i32) void;
2628
27export fn zig_five_integers(a: i32, b: i32, c: i32, d: i32, e: i32) void {29export fn zig_five_integers(a: i32, b: i32, c: i32, d: i32, e: i32) void {
28 expect(a == 12) catch @panic("test failure");30 expect(a == 12) catch @panic("test failure: zig_five_integers 12");
29 expect(b == 34) catch @panic("test failure");31 expect(b == 34) catch @panic("test failure: zig_five_integers 34");
30 expect(c == 56) catch @panic("test failure");32 expect(c == 56) catch @panic("test failure: zig_five_integers 56");
31 expect(d == 78) catch @panic("test failure");33 expect(d == 78) catch @panic("test failure: zig_five_integers 78");
32 expect(e == 90) catch @panic("test failure");34 expect(e == 90) catch @panic("test failure: zig_five_integers 90");
33}35}
3436
35test "C ABI integers" {37test "C ABI integers" {
...@@ -37,37 +39,52 @@ test "C ABI integers" {...@@ -37,37 +39,52 @@ test "C ABI integers" {
37 c_u16(0xfffe);39 c_u16(0xfffe);
38 c_u32(0xfffffffd);40 c_u32(0xfffffffd);
39 c_u64(0xfffffffffffffffc);41 c_u64(0xfffffffffffffffc);
42 c_struct_u128(.{ .value = 0xfffffffffffffffc });
4043
41 c_i8(-1);44 c_i8(-1);
42 c_i16(-2);45 c_i16(-2);
43 c_i32(-3);46 c_i32(-3);
44 c_i64(-4);47 c_i64(-4);
48 c_struct_i128(.{ .value = -6 });
45 c_five_integers(12, 34, 56, 78, 90);49 c_five_integers(12, 34, 56, 78, 90);
46}50}
4751
48export fn zig_u8(x: u8) void {52export fn zig_u8(x: u8) void {
49 expect(x == 0xff) catch @panic("test failure");53 expect(x == 0xff) catch @panic("test failure: zig_u8");
50}54}
51export fn zig_u16(x: u16) void {55export fn zig_u16(x: u16) void {
52 expect(x == 0xfffe) catch @panic("test failure");56 expect(x == 0xfffe) catch @panic("test failure: zig_u16");
53}57}
54export fn zig_u32(x: u32) void {58export fn zig_u32(x: u32) void {
55 expect(x == 0xfffffffd) catch @panic("test failure");59 expect(x == 0xfffffffd) catch @panic("test failure: zig_u32");
56}60}
57export fn zig_u64(x: u64) void {61export fn zig_u64(x: u64) void {
58 expect(x == 0xfffffffffffffffc) catch @panic("test failure");62 expect(x == 0xfffffffffffffffc) catch @panic("test failure: zig_u64");
59}63}
60export fn zig_i8(x: i8) void {64export fn zig_i8(x: i8) void {
61 expect(x == -1) catch @panic("test failure");65 expect(x == -1) catch @panic("test failure: zig_i8");
62}66}
63export fn zig_i16(x: i16) void {67export fn zig_i16(x: i16) void {
64 expect(x == -2) catch @panic("test failure");68 expect(x == -2) catch @panic("test failure: zig_i16");
65}69}
66export fn zig_i32(x: i32) void {70export fn zig_i32(x: i32) void {
67 expect(x == -3) catch @panic("test failure");71 expect(x == -3) catch @panic("test failure: zig_i32");
68}72}
69export fn zig_i64(x: i64) void {73export fn zig_i64(x: i64) void {
70 expect(x == -4) catch @panic("test failure");74 expect(x == -4) catch @panic("test failure: zig_i64");
75}
76
77const I128 = extern struct {
78 value: i128,
79};
80const U128 = extern struct {
81 value: u128,
82};
83export fn zig_struct_i128(a: I128) void {
84 expect(a.value == -6) catch @panic("test failure: zig_struct_i128");
85}
86export fn zig_struct_u128(a: U128) void {
87 expect(a.value == 0xfffffffffffffffc) catch @panic("test failure: zig_struct_u128");
71}88}
7289
73extern fn c_f32(f32) void;90extern fn c_f32(f32) void;
...@@ -77,11 +94,11 @@ extern fn c_f64(f64) void;...@@ -77,11 +94,11 @@ extern fn c_f64(f64) void;
77extern fn c_five_floats(f32, f32, f32, f32, f32) void;94extern fn c_five_floats(f32, f32, f32, f32, f32) void;
7895
79export fn zig_five_floats(a: f32, b: f32, c: f32, d: f32, e: f32) void {96export fn zig_five_floats(a: f32, b: f32, c: f32, d: f32, e: f32) void {
80 expect(a == 1.0) catch @panic("test failure");97 expect(a == 1.0) catch @panic("test failure: zig_five_floats 1.0");
81 expect(b == 2.0) catch @panic("test failure");98 expect(b == 2.0) catch @panic("test failure: zig_five_floats 2.0");
82 expect(c == 3.0) catch @panic("test failure");99 expect(c == 3.0) catch @panic("test failure: zig_five_floats 3.0");
83 expect(d == 4.0) catch @panic("test failure");100 expect(d == 4.0) catch @panic("test failure: zig_five_floats 4.0");
84 expect(e == 5.0) catch @panic("test failure");101 expect(e == 5.0) catch @panic("test failure: zig_five_floats 5.0");
85}102}
86103
87test "C ABI floats" {104test "C ABI floats" {
...@@ -91,10 +108,10 @@ test "C ABI floats" {...@@ -91,10 +108,10 @@ test "C ABI floats" {
91}108}
92109
93export fn zig_f32(x: f32) void {110export fn zig_f32(x: f32) void {
94 expect(x == 12.34) catch @panic("test failure");111 expect(x == 12.34) catch @panic("test failure: zig_f32");
95}112}
96export fn zig_f64(x: f64) void {113export fn zig_f64(x: f64) void {
97 expect(x == 56.78) catch @panic("test failure");114 expect(x == 56.78) catch @panic("test failure: zig_f64");
98}115}
99116
100extern fn c_ptr(*anyopaque) void;117extern fn c_ptr(*anyopaque) void;
...@@ -104,7 +121,7 @@ test "C ABI pointer" {...@@ -104,7 +121,7 @@ test "C ABI pointer" {
104}121}
105122
106export fn zig_ptr(x: *anyopaque) void {123export fn zig_ptr(x: *anyopaque) void {
107 expect(@ptrToInt(x) == 0xdeadbeef) catch @panic("test failure");124 expect(@ptrToInt(x) == 0xdeadbeef) catch @panic("test failure: zig_ptr");
108}125}
109126
110extern fn c_bool(bool) void;127extern fn c_bool(bool) void;
...@@ -114,7 +131,7 @@ test "C ABI bool" {...@@ -114,7 +131,7 @@ test "C ABI bool" {
114}131}
115132
116export fn zig_bool(x: bool) void {133export fn zig_bool(x: bool) void {
117 expect(x) catch @panic("test failure");134 expect(x) catch @panic("test failure: zig_bool");
118}135}
119136
120const BigStruct = extern struct {137const BigStruct = extern struct {
...@@ -138,11 +155,11 @@ test "C ABI big struct" {...@@ -138,11 +155,11 @@ test "C ABI big struct" {
138}155}
139156
140export fn zig_big_struct(x: BigStruct) void {157export fn zig_big_struct(x: BigStruct) void {
141 expect(x.a == 1) catch @panic("test failure");158 expect(x.a == 1) catch @panic("test failure: zig_big_struct 1");
142 expect(x.b == 2) catch @panic("test failure");159 expect(x.b == 2) catch @panic("test failure: zig_big_struct 2");
143 expect(x.c == 3) catch @panic("test failure");160 expect(x.c == 3) catch @panic("test failure: zig_big_struct 3");
144 expect(x.d == 4) catch @panic("test failure");161 expect(x.d == 4) catch @panic("test failure: zig_big_struct 4");
145 expect(x.e == 5) catch @panic("test failure");162 expect(x.e == 5) catch @panic("test failure: zig_big_struct 5");
146}163}
147164
148const BigUnion = extern union {165const BigUnion = extern union {
...@@ -164,11 +181,11 @@ test "C ABI big union" {...@@ -164,11 +181,11 @@ test "C ABI big union" {
164}181}
165182
166export fn zig_big_union(x: BigUnion) void {183export fn zig_big_union(x: BigUnion) void {
167 expect(x.a.a == 1) catch @panic("test failure");184 expect(x.a.a == 1) catch @panic("test failure: zig_big_union a");
168 expect(x.a.b == 2) catch @panic("test failure");185 expect(x.a.b == 2) catch @panic("test failure: zig_big_union b");
169 expect(x.a.c == 3) catch @panic("test failure");186 expect(x.a.c == 3) catch @panic("test failure: zig_big_union c");
170 expect(x.a.d == 4) catch @panic("test failure");187 expect(x.a.d == 4) catch @panic("test failure: zig_big_union d");
171 expect(x.a.e == 5) catch @panic("test failure");188 expect(x.a.e == 5) catch @panic("test failure: zig_big_union e");
172}189}
173190
174const MedStructMixed = extern struct {191const MedStructMixed = extern struct {