authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-09 13:23:20-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-11 12:14:32-07:00
log0d006afb23aa5d0308adb56d2578b4340f34231e
tree0ced413a891e61d22132f41e2661e96629cba5b6
parentbf6af1963cfb3451b3338d7488ec26f5fb7af0ed

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
...@@ -8255,23 +8255,53 @@ Error file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents_buf) {...@@ -8255,23 +8255,53 @@ Error file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents_buf) {
82558255
8256static X64CABIClass type_windows_abi_x86_64_class(CodeGen *g, ZigType *ty, size_t ty_size) {8256static X64CABIClass type_windows_abi_x86_64_class(CodeGen *g, ZigType *ty, size_t ty_size) {
8257 // https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-20178257 // https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-2017
8258 switch (ty_size) {
8259 case 1:
8260 case 2:
8261 case 4:
8262 case 8:
8263 break;
8264 case 16:
8265 return (ty->id == ZigTypeIdVector) ? X64CABIClass_SSE : X64CABIClass_MEMORY;
8266 default:
8267 return X64CABIClass_MEMORY;
8268 }
8258 switch (ty->id) {8269 switch (ty->id) {
8259 case ZigTypeIdEnum:8270 case ZigTypeIdInvalid:
8271 case ZigTypeIdMetaType:
8272 case ZigTypeIdComptimeFloat:
8273 case ZigTypeIdComptimeInt:
8274 case ZigTypeIdNull:
8275 case ZigTypeIdUndefined:
8276 case ZigTypeIdBoundFn:
8277 case ZigTypeIdOpaque:
8278 case ZigTypeIdEnumLiteral:
8279 zig_unreachable();
8280
8281 case ZigTypeIdFn:
8282 case ZigTypeIdPointer:
8260 case ZigTypeIdInt:8283 case ZigTypeIdInt:
8261 case ZigTypeIdBool:8284 case ZigTypeIdBool:
8285 case ZigTypeIdEnum:
8286 case ZigTypeIdVoid:
8287 case ZigTypeIdUnreachable:
8288 case ZigTypeIdErrorSet:
8289 case ZigTypeIdErrorUnion:
8290 case ZigTypeIdStruct:
8291 case ZigTypeIdUnion:
8292 case ZigTypeIdOptional:
8293 case ZigTypeIdFnFrame:
8294 case ZigTypeIdAnyFrame:
8262 return X64CABIClass_INTEGER;8295 return X64CABIClass_INTEGER;
8296
8263 case ZigTypeIdFloat:8297 case ZigTypeIdFloat:
8264 case ZigTypeIdVector:8298 case ZigTypeIdVector:
8265 return X64CABIClass_SSE;8299 return X64CABIClass_SSE;
8266 case ZigTypeIdStruct:8300
8267 case ZigTypeIdUnion: {8301 case ZigTypeIdArray:
8268 if (ty_size <= 8)
8269 return X64CABIClass_INTEGER;
8270 return X64CABIClass_MEMORY;
8271 }
8272 default:
8273 return X64CABIClass_Unknown;8302 return X64CABIClass_Unknown;
8274 }8303 }
8304 zig_unreachable();
8275}8305}
82768306
8277static X64CABIClass type_system_V_abi_x86_64_class(CodeGen *g, ZigType *ty, size_t ty_size) {8307static X64CABIClass type_system_V_abi_x86_64_class(CodeGen *g, ZigType *ty, size_t ty_size) {
...@@ -8350,17 +8380,19 @@ static X64CABIClass type_system_V_abi_x86_64_class(CodeGen *g, ZigType *ty, size...@@ -8350,17 +8380,19 @@ static X64CABIClass type_system_V_abi_x86_64_class(CodeGen *g, ZigType *ty, size
83508380
8351X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) {8381X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) {
8352 Error err;8382 Error err;
8353
8354 const size_t ty_size = type_size(g, ty);8383 const size_t ty_size = type_size(g, ty);
8384
8385 if (g->zig_target->os == OsWindows || g->zig_target->os == OsUefi) {
8386 return type_windows_abi_x86_64_class(g, ty, ty_size);
8387 }
8388
8355 ZigType *ptr_type;8389 ZigType *ptr_type;
8356 if ((err = get_codegen_ptr_type(g, ty, &ptr_type))) return X64CABIClass_Unknown;8390 if ((err = get_codegen_ptr_type(g, ty, &ptr_type))) return X64CABIClass_Unknown;
8357 if (ptr_type != nullptr)8391 if (ptr_type != nullptr)
8358 return X64CABIClass_INTEGER;8392 return X64CABIClass_INTEGER;
83598393
8360 if (g->zig_target->os == OsWindows || g->zig_target->os == OsUefi) {8394 if (g->zig_target->arch == ZigLLVM_aarch64 ||
8361 return type_windows_abi_x86_64_class(g, ty, ty_size);8395 g->zig_target->arch == ZigLLVM_aarch64_be)
8362 } else if (g->zig_target->arch == ZigLLVM_aarch64 ||
8363 g->zig_target->arch == ZigLLVM_aarch64_be)
8364 {8396 {
8365 X64CABIClass result = type_system_V_abi_x86_64_class(g, ty, ty_size);8397 X64CABIClass result = type_system_V_abi_x86_64_class(g, ty, ty_size);
8366 return (result == X64CABIClass_MEMORY) ? X64CABIClass_MEMORY_nobyval : result;8398 return (result == X64CABIClass_MEMORY) ? X64CABIClass_MEMORY_nobyval : result;
...@@ -8660,14 +8692,23 @@ static Error resolve_llvm_c_abi_type(CodeGen *g, ZigType *ty) {...@@ -8660,14 +8692,23 @@ static Error resolve_llvm_c_abi_type(CodeGen *g, ZigType *ty) {
8660 if (ty->data.structure.fields[i]->offset >= 8) {8692 if (ty->data.structure.fields[i]->offset >= 8) {
8661 eightbyte_index = 1;8693 eightbyte_index = 1;
8662 }8694 }
8663 X64CABIClass field_class = type_c_abi_x86_64_class(g, ty->data.structure.fields[i]->type_entry);8695 ZigType *field_ty = ty->data.structure.fields[i]->type_entry;
8696 X64CABIClass field_class = type_c_abi_x86_64_class(g, field_ty);
86648697
8665 if (field_class == X64CABIClass_INTEGER) {8698 if (field_class == X64CABIClass_INTEGER) {
8666 type_classes[eightbyte_index] = X64CABIClass_INTEGER;8699 type_classes[eightbyte_index] = X64CABIClass_INTEGER;
8667 } else if (type_classes[eightbyte_index] == X64CABIClass_Unknown) {8700 } else if (type_classes[eightbyte_index] == X64CABIClass_Unknown) {
8668 type_classes[eightbyte_index] = field_class;8701 type_classes[eightbyte_index] = field_class;
8669 }8702 }
8670 type_sizes[eightbyte_index] += ty->data.structure.fields[i]->type_entry->abi_size;8703 if (field_ty->abi_size > 8) {
8704 assert(eightbyte_index == 0);
8705 type_sizes[0] = 8;
8706 type_sizes[1] = field_ty->abi_size - 8;
8707 type_classes[1] = type_classes[0];
8708 eightbyte_index = 1;
8709 } else {
8710 type_sizes[eightbyte_index] += field_ty->abi_size;
8711 }
8671 }8712 }
86728713
8673 LLVMTypeRef return_elem_types[] = {8714 LLVMTypeRef return_elem_types[] = {
...@@ -8956,8 +8997,12 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS...@@ -8956,8 +8997,12 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
8956 struct_type->data.structure.llvm_full_type_queue_index = SIZE_MAX;8997 struct_type->data.structure.llvm_full_type_queue_index = SIZE_MAX;
8957 }8998 }
89588999
8959 if (struct_type->abi_size <= 16 && (struct_type->data.structure.layout == ContainerLayoutExtern || struct_type->data.structure.layout == ContainerLayoutPacked))9000 if (struct_type->abi_size <= 16 &&
9001 (struct_type->data.structure.layout == ContainerLayoutExtern ||
9002 struct_type->data.structure.layout == ContainerLayoutPacked))
9003 {
8960 resolve_llvm_c_abi_type(g, struct_type);9004 resolve_llvm_c_abi_type(g, struct_type);
9005 }
8961}9006}
89629007
8963// This is to be used instead of void for debug info types, to avoid tripping9008// 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 {