authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-08-06 07:46:31+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-08-06 07:46:31+02:00
log16b42da3fd359bf5ae602aa0153e3ec1d6d14822
tree2de00e8cb5e557a1b902273dec1288c81e48345b
parent8901bfe190e2360f934c6e4330cac5eed6c8712b
parent46f98e366b10e1db59ca776c8cefcf827a66ffde

Merge pull request 'fix various C ABI bugs' (#36404) from Techatrix/zig:c-abi-fixes into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36404 Reviewed-by: Andrew Kelley <andrew@ziglang.org>

6 files changed, 427 insertions(+), 53 deletions(-)

src/codegen/loongarch/abi.zig+1-1
......@@ -95,7 +95,7 @@ const Classifier = struct {
9595 var class: Class = .ignored;
9696 const elem_ty = ty.childType(c.zcu);
9797 const elem_class = c.classifyType(elem_ty);
98 for (0..std.math.lossyCast(usize, ty.arrayLen(c.zcu))) |_| {
98 for (0..std.math.lossyCast(usize, ty.arrayLenIncludingSentinel(c.zcu))) |_| {
9999 class = class.combineMember(elem_class, elem_ty);
100100 if (class == .address) break;
101101 }
src/codegen/s390x/abi.zig+1-8
......@@ -45,14 +45,7 @@ pub fn classifyType(ty: Type, context: Context, zcu: *Zcu) Class {
4545 128 => return .pointer,
4646 },
4747 .pointer, .optional => return .simple,
48 .array => switch (ty.arrayLen(zcu)) {
49 0 => return .none,
50 1 => switch (context) {
51 .ret => {},
52 .arg => return classifyType(ty.childType(zcu), context, zcu),
53 },
54 else => {},
55 },
48 .array => {},
5649 .@"struct", .@"union" => |tag| switch (ty.containerLayout(zcu)) {
5750 .auto => unreachable,
5851 .@"extern" => switch (context) {
src/codegen/wasm/abi.zig+33-11
......@@ -71,20 +71,35 @@ pub fn classifyTypeForLlvm(ty: Type, zcu: *const Zcu) LlvmClass {
7171 },
7272 .@"struct" => {
7373 const struct_type = zcu.typeToStruct(ty).?;
74 if (struct_type.layout == .@"packed") {
75 return .{ .direct = ty };
76 }
77 if (struct_type.field_types.len > 1) {
78 // The struct type is non-scalar.
79 return .indirect;
74 switch (struct_type.layout) {
75 .auto => unreachable,
76 .@"packed" => return .{ .direct = ty },
77 .@"extern" => {},
8078 }
81 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[0]);
82 const explicit_align = struct_type.field_aligns.getOrNone(ip, 0);
83 if (explicit_align != .none) {
84 if (explicit_align.compareStrict(.gt, field_ty.abiAlignment(zcu)))
79 var opt_single_field_ty: ?Type = null;
80 for (struct_type.field_types.get(ip), 0..) |field_ty_index, field_index| {
81 const field_ty: Type = .fromInterned(field_ty_index);
82 if (!field_ty.hasRuntimeBits(zcu)) continue;
83
84 if (opt_single_field_ty != null) {
8585 return .indirect;
86 }
87
88 const field_align = struct_type.field_aligns.getOrNone(ip, field_index);
89 if (field_align != .none and field_align.compareStrict(.gt, field_ty.abiAlignment(zcu))) {
90 return .indirect;
91 }
92 opt_single_field_ty = field_ty;
93 }
94 const single_field_ty = opt_single_field_ty.?;
95 if (single_field_ty.zigTypeTag(zcu) == .array) {
96 switch (single_field_ty.arrayLenIncludingSentinel(zcu)) {
97 0 => unreachable,
98 1 => return classifyTypeForLlvm(single_field_ty.childType(zcu), zcu),
99 else => {},
100 }
86101 }
87 return classifyTypeForLlvm(field_ty, zcu);
102 return classifyTypeForLlvm(single_field_ty, zcu);
88103 },
89104 .@"union" => {
90105 const union_obj = zcu.typeToUnion(ty).?;
......@@ -95,6 +110,13 @@ pub fn classifyTypeForLlvm(ty: Type, zcu: *const Zcu) LlvmClass {
95110 assert(layout.tag_size == 0);
96111 if (union_obj.field_types.len > 1) return .indirect;
97112 const first_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[0]);
113 if (first_field_ty.zigTypeTag(zcu) == .array) {
114 switch (first_field_ty.arrayLenIncludingSentinel(zcu)) {
115 0 => unreachable,
116 1 => return classifyTypeForLlvm(first_field_ty.childType(zcu), zcu),
117 else => {},
118 }
119 }
98120 return classifyTypeForLlvm(first_field_ty, zcu);
99121 },
100122 .error_union,
src/codegen/x86_64/abi.zig+1-1
......@@ -443,7 +443,7 @@ fn classifySystemVArray(
443443 const field_classes = std.mem.sliceTo(&classifySystemV(array_ty.childType(zcu), zcu, target, .other), .none);
444444 var byte_offset = starting_byte_offset;
445445 const elem_size = array_ty.childType(zcu).abiSize(zcu);
446 for (0..@intCast(array_ty.arrayLen(zcu))) |_| {
446 for (0..@intCast(array_ty.arrayLenIncludingSentinel(zcu))) |_| {
447447 for (result[@intCast(byte_offset / 8)..][0..field_classes.len], field_classes) |*result_class, field_class|
448448 result_class.* = result_class.combineSystemV(field_class);
449449 byte_offset += elem_size;
test/c_abi/cfuncs.c+136
......@@ -15194,6 +15194,22 @@ void c_test_struct_f32_f32_f32_f32_f32(void) {
1519415194 zig_struct_f32_f32_f32_f32_f32((struct Struct_f32_f32_f32_f32_f32){ .a = 6, .b = 7, .c = 8, .d = 9, .e = 10 }, 11);
1519515195}
1519615196
15197struct Struct_f32 zig_ret_struct_void_f32(void);
15198void zig_struct_void_f32(struct Struct_f32, size_t);
15199
15200struct Struct_f32 c_ret_struct_void_f32(void) {
15201 return (struct Struct_f32){ .a = 4 };
15202}
15203void c_struct_void_f32(struct Struct_f32 s, size_t i) {
15204 assert_or_panic(s.a == 5);
15205 assert_or_panic(i == 6);
15206}
15207void c_test_struct_void_f32(void) {
15208 struct Struct_f32 s = zig_ret_struct_void_f32();
15209 assert_or_panic(s.a == 1);
15210 zig_struct_void_f32((struct Struct_f32){ .a = 2 }, 3);
15211}
15212
1519715213struct Struct_array_1_f32 {
1519815214 float a[1];
1519915215};
......@@ -15314,6 +15330,106 @@ void c_test_struct_array_5_f32(void) {
1531415330 zig_struct_array_5_f32((struct Struct_array_5_f32){ .a = { 6, 7, 8, 9, 10 } }, 11);
1531515331}
1531615332
15333struct Struct_array_1_f32 zig_ret_struct_array_0_sentinel_f32(void);
15334void zig_struct_array_0_sentinel_f32(struct Struct_array_1_f32, size_t);
15335
15336struct Struct_array_1_f32 c_ret_struct_array_0_sentinel_f32(void) {
15337 return (struct Struct_array_1_f32){ .a = { 0x1e1 } };
15338}
15339void c_struct_array_0_sentinel_f32(struct Struct_array_1_f32 s, size_t i) {
15340 assert_or_panic(s.a[0] == 0x1e1);
15341 assert_or_panic(i == 2);
15342}
15343void c_test_struct_array_0_sentinel_f32(void) {
15344 struct Struct_array_1_f32 s = zig_ret_struct_array_0_sentinel_f32();
15345 assert_or_panic(s.a[0] == 0x1e1);
15346 zig_struct_array_0_sentinel_f32((struct Struct_array_1_f32){ .a = { 0x1e1 } }, 1);
15347}
15348
15349struct Struct_array_2_f32 zig_ret_struct_array_1_sentinel_f32(void);
15350void zig_struct_array_1_sentinel_f32(struct Struct_array_2_f32, size_t);
15351
15352struct Struct_array_2_f32 c_ret_struct_array_1_sentinel_f32(void) {
15353 return (struct Struct_array_2_f32){ .a = { 4, 0x1e1 } };
15354}
15355void c_struct_array_1_sentinel_f32(struct Struct_array_2_f32 s, size_t i) {
15356 assert_or_panic(s.a[0] == 5);
15357 assert_or_panic(s.a[1] == 0x1e1);
15358 assert_or_panic(i == 6);
15359}
15360void c_test_struct_array_1_sentinel_f32(void) {
15361 struct Struct_array_2_f32 s = zig_ret_struct_array_1_sentinel_f32();
15362 assert_or_panic(s.a[0] == 1);
15363 assert_or_panic(s.a[1] == 0x1e1);
15364 zig_struct_array_1_sentinel_f32((struct Struct_array_2_f32){ .a = { 2, 0x1e1 } }, 3);
15365}
15366
15367struct Struct_array_3_f32 zig_ret_struct_array_2_sentinel_f32(void);
15368void zig_struct_array_2_sentinel_f32(struct Struct_array_3_f32, size_t);
15369
15370struct Struct_array_3_f32 c_ret_struct_array_2_sentinel_f32(void) {
15371 return (struct Struct_array_3_f32){ .a = { 6, 7, 0x1e1 } };
15372}
15373void c_struct_array_2_sentinel_f32(struct Struct_array_3_f32 s, size_t i) {
15374 assert_or_panic(s.a[0] == 8);
15375 assert_or_panic(s.a[1] == 9);
15376 assert_or_panic(s.a[2] == 0x1e1);
15377 assert_or_panic(i == 10);
15378}
15379void c_test_struct_array_2_sentinel_f32(void) {
15380 struct Struct_array_3_f32 s = zig_ret_struct_array_2_sentinel_f32();
15381 assert_or_panic(s.a[0] == 1);
15382 assert_or_panic(s.a[1] == 2);
15383 assert_or_panic(s.a[2] == 0x1e1);
15384 zig_struct_array_2_sentinel_f32((struct Struct_array_3_f32){ .a = { 3, 4, 0x1e1 } }, 5);
15385}
15386
15387struct Struct_array_4_f32 zig_ret_struct_array_3_sentinel_f32(void);
15388void zig_struct_array_3_sentinel_f32(struct Struct_array_4_f32, size_t);
15389
15390struct Struct_array_4_f32 c_ret_struct_array_3_sentinel_f32(void) {
15391 return (struct Struct_array_4_f32){ .a = { 8, 9, 10, 0x1e1 } };
15392}
15393void c_struct_array_3_sentinel_f32(struct Struct_array_4_f32 s, size_t i) {
15394 assert_or_panic(s.a[0] == 11);
15395 assert_or_panic(s.a[1] == 12);
15396 assert_or_panic(s.a[2] == 13);
15397 assert_or_panic(s.a[3] == 0x1e1);
15398 assert_or_panic(i == 14);
15399}
15400void c_test_struct_array_3_sentinel_f32(void) {
15401 struct Struct_array_4_f32 s = zig_ret_struct_array_3_sentinel_f32();
15402 assert_or_panic(s.a[0] == 1);
15403 assert_or_panic(s.a[1] == 2);
15404 assert_or_panic(s.a[2] == 3);
15405 assert_or_panic(s.a[3] == 0x1e1);
15406 zig_struct_array_3_sentinel_f32((struct Struct_array_4_f32){ .a = { 4, 5, 6, 0x1e1 } }, 7);
15407}
15408
15409struct Struct_array_5_f32 zig_ret_struct_array_4_sentinel_f32(void);
15410void zig_struct_array_4_sentinel_f32(struct Struct_array_5_f32, size_t);
15411
15412struct Struct_array_5_f32 c_ret_struct_array_4_sentinel_f32(void) {
15413 return (struct Struct_array_5_f32){ .a = { 10, 11, 12, 13, 0x1e1 } };
15414}
15415void c_struct_array_4_sentinel_f32(struct Struct_array_5_f32 s, size_t i) {
15416 assert_or_panic(s.a[0] == 14);
15417 assert_or_panic(s.a[1] == 15);
15418 assert_or_panic(s.a[2] == 16);
15419 assert_or_panic(s.a[3] == 17);
15420 assert_or_panic(s.a[4] == 0x1e1);
15421 assert_or_panic(i == 18);
15422}
15423void c_test_struct_array_4_sentinel_f32(void) {
15424 struct Struct_array_5_f32 s = zig_ret_struct_array_4_sentinel_f32();
15425 assert_or_panic(s.a[0] == 1);
15426 assert_or_panic(s.a[1] == 2);
15427 assert_or_panic(s.a[2] == 3);
15428 assert_or_panic(s.a[3] == 4);
15429 assert_or_panic(s.a[4] == 0x1e1);
15430 zig_struct_array_4_sentinel_f32((struct Struct_array_5_f32){ .a = { 5, 6, 7, 8, 0x1e1 } }, 9);
15431}
15432
1531715433struct Struct_f32a8 {
1531815434 alignas(8) float a;
1531915435};
......@@ -15649,6 +15765,26 @@ void c_test_struct_array_5_f64(void) {
1564915765 zig_struct_array_5_f64((struct Struct_array_5_f64){ .a = { 6, 7, 8, 9, 10 } }, 11);
1565015766}
1565115767
15768union Union_f64 {
15769 double a;
15770};
15771
15772union Union_f64 zig_ret_union_f64(void);
15773void zig_union_f64(union Union_f64, size_t);
15774
15775union Union_f64 c_ret_union_f64(void) {
15776 return (union Union_f64){ .a = 4 };
15777}
15778void c_union_f64(union Union_f64 s, size_t i) {
15779 assert_or_panic(s.a == 5);
15780 assert_or_panic(i == 6);
15781}
15782void c_test_union_f64(void) {
15783 union Union_f64 s = zig_ret_union_f64();
15784 assert_or_panic(s.a == 1);
15785 zig_union_f64((union Union_f64){ .a = 2 }, 3);
15786}
15787
1565215788struct Struct_u32_Union_u32_u32u32 {
1565315789 uint32_t a;
1565415790 union {
test/c_abi/main.zig+255-32
......@@ -16103,24 +16103,44 @@ test "struct f32, f32, f32, f32, f32" {
1610316103 c_test_struct_f32_f32_f32_f32_f32();
1610416104}
1610516105
16106const Struct_void_f32 = extern struct {
16107 _: void = {},
16108 a: f32,
16109};
16110
16111export fn zig_ret_struct_void_f32() Struct_void_f32 {
16112 return .{ .a = 1 };
16113}
16114export fn zig_struct_void_f32(s: Struct_void_f32, i: usize) void {
16115 expect(s.a == 2) catch @panic("test failure");
16116 expect(i == 3) catch @panic("test failure");
16117}
16118
16119extern fn c_ret_struct_void_f32() Struct_void_f32;
16120extern fn c_struct_void_f32(Struct_void_f32, usize) void;
16121extern fn c_test_struct_void_f32() void;
16122
16123test "struct void, f32" {
16124 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16125 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16126 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
16127
16128 const s = c_ret_struct_void_f32();
16129 try expect(s.a == 4);
16130 c_struct_void_f32(.{ .a = 5 }, 6);
16131 c_test_struct_void_f32();
16132}
16133
1610616134const Struct_array_1_f32 = extern struct {
1610716135 a: [1]f32,
1610816136};
1610916137
16110comptime {
16111 skip: {
16112 if (builtin.cpu.arch.isWasm()) break :skip;
16113
16114 _ = struct {
16115 export fn zig_ret_struct_array_1_f32() Struct_array_1_f32 {
16116 return .{ .a = .{1} };
16117 }
16118 export fn zig_struct_array_1_f32(s: Struct_array_1_f32, i: usize) void {
16119 expect(s.a[0] == 2) catch @panic("test failure");
16120 expect(i == 3) catch @panic("test failure");
16121 }
16122 };
16123 }
16138export fn zig_ret_struct_array_1_f32() Struct_array_1_f32 {
16139 return .{ .a = .{1} };
16140}
16141export fn zig_struct_array_1_f32(s: Struct_array_1_f32, i: usize) void {
16142 expect(s.a[0] == 2) catch @panic("test failure");
16143 expect(i == 3) catch @panic("test failure");
1612416144}
1612516145
1612616146extern fn c_ret_struct_array_1_f32() Struct_array_1_f32;
......@@ -16133,8 +16153,6 @@ test "struct [1]f32" {
1613316153 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1613416154 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1613516155 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16136 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16137 if (builtin.cpu.arch.isWasm()) return error.SkipZigTest;
1613816156
1613916157 const s = c_ret_struct_array_1_f32();
1614016158 try expect(s.a[0] == 4);
......@@ -16278,6 +16296,191 @@ test "struct [5]f32" {
1627816296 c_test_struct_array_5_f32();
1627916297}
1628016298
16299const Struct_array_0_sentinel_f32 = extern struct {
16300 a: [0:0x1e1]f32,
16301};
16302
16303export fn zig_ret_struct_array_0_sentinel_f32() Struct_array_0_sentinel_f32 {
16304 return .{ .a = .{} };
16305}
16306export fn zig_struct_array_0_sentinel_f32(s: Struct_array_0_sentinel_f32, i: usize) void {
16307 var sentinel_index: usize = 0;
16308 _ = &sentinel_index;
16309 expect(s.a[sentinel_index] == 0x1e1) catch @panic("test failure");
16310 expect(i == 1) catch @panic("test failure");
16311}
16312
16313extern fn c_ret_struct_array_0_sentinel_f32() Struct_array_0_sentinel_f32;
16314extern fn c_struct_array_0_sentinel_f32(Struct_array_0_sentinel_f32, usize) void;
16315extern fn c_test_struct_array_0_sentinel_f32() void;
16316
16317test "struct [0:sentinel]f32" {
16318 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
16319 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16320 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16321 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16322 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16323
16324 var sentinel_index: usize = 0;
16325 _ = &sentinel_index;
16326 const s = c_ret_struct_array_0_sentinel_f32();
16327 try expect(s.a[sentinel_index] == 0x1e1);
16328 c_struct_array_0_sentinel_f32(.{ .a = .{} }, 2);
16329 c_test_struct_array_0_sentinel_f32();
16330}
16331
16332const Struct_array_1_sentinel_f32 = extern struct {
16333 a: [1:0x1e1]f32,
16334};
16335
16336export fn zig_ret_struct_array_1_sentinel_f32() Struct_array_1_sentinel_f32 {
16337 return .{ .a = .{1} };
16338}
16339export fn zig_struct_array_1_sentinel_f32(s: Struct_array_1_sentinel_f32, i: usize) void {
16340 var sentinel_index: usize = 1;
16341 _ = &sentinel_index;
16342 expect(s.a[0] == 2) catch @panic("test failure");
16343 expect(s.a[sentinel_index] == 0x1e1) catch @panic("test failure");
16344 expect(i == 3) catch @panic("test failure");
16345}
16346
16347extern fn c_ret_struct_array_1_sentinel_f32() Struct_array_1_sentinel_f32;
16348extern fn c_struct_array_1_sentinel_f32(Struct_array_1_sentinel_f32, usize) void;
16349extern fn c_test_struct_array_1_sentinel_f32() void;
16350
16351test "struct [1:sentinel]f32" {
16352 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
16353 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16354 if (builtin.cpu.arch == .loongarch64 and builtin.abi.float() == .hard) return error.SkipZigTest;
16355 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16356 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16357 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16358
16359 var sentinel_index: usize = 1;
16360 _ = &sentinel_index;
16361 const s = c_ret_struct_array_1_sentinel_f32();
16362 try expect(s.a[0] == 4);
16363 try expect(s.a[sentinel_index] == 0x1e1);
16364 c_struct_array_1_sentinel_f32(.{ .a = .{5} }, 6);
16365 c_test_struct_array_1_sentinel_f32();
16366}
16367
16368const Struct_array_2_sentinel_f32 = extern struct {
16369 a: [2:0x1e1]f32,
16370};
16371
16372export fn zig_ret_struct_array_2_sentinel_f32() Struct_array_2_sentinel_f32 {
16373 return .{ .a = .{ 1, 2 } };
16374}
16375export fn zig_struct_array_2_sentinel_f32(s: Struct_array_2_sentinel_f32, i: usize) void {
16376 var sentinel_index: usize = 2;
16377 _ = &sentinel_index;
16378 expect(s.a[0] == 3) catch @panic("test failure");
16379 expect(s.a[1] == 4) catch @panic("test failure");
16380 expect(s.a[sentinel_index] == 0x1e1) catch @panic("test failure");
16381 expect(i == 5) catch @panic("test failure");
16382}
16383
16384extern fn c_ret_struct_array_2_sentinel_f32() Struct_array_2_sentinel_f32;
16385extern fn c_struct_array_2_sentinel_f32(Struct_array_2_sentinel_f32, usize) void;
16386extern fn c_test_struct_array_2_sentinel_f32() void;
16387
16388test "struct [2:sentinel]f32" {
16389 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
16390 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16391 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16392 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16393 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16394
16395 var sentinel_index: usize = 2;
16396 _ = &sentinel_index;
16397 const s = c_ret_struct_array_2_sentinel_f32();
16398 try expect(s.a[0] == 6);
16399 try expect(s.a[1] == 7);
16400 try expect(s.a[sentinel_index] == 0x1e1);
16401 c_struct_array_2_sentinel_f32(.{ .a = .{ 8, 9 } }, 10);
16402 c_test_struct_array_2_sentinel_f32();
16403}
16404
16405const Struct_array_3_sentinel_f32 = extern struct {
16406 a: [3:0x1e1]f32,
16407};
16408
16409export fn zig_ret_struct_array_3_sentinel_f32() Struct_array_3_sentinel_f32 {
16410 return .{ .a = .{ 1, 2, 3 } };
16411}
16412export fn zig_struct_array_3_sentinel_f32(s: Struct_array_3_sentinel_f32, i: usize) void {
16413 var sentinel_index: usize = 3;
16414 _ = &sentinel_index;
16415 expect(s.a[0] == 4) catch @panic("test failure");
16416 expect(s.a[1] == 5) catch @panic("test failure");
16417 expect(s.a[2] == 6) catch @panic("test failure");
16418 expect(s.a[sentinel_index] == 0x1e1) catch @panic("test failure");
16419 expect(i == 7) catch @panic("test failure");
16420}
16421
16422extern fn c_ret_struct_array_3_sentinel_f32() Struct_array_3_sentinel_f32;
16423extern fn c_struct_array_3_sentinel_f32(Struct_array_3_sentinel_f32, usize) void;
16424extern fn c_test_struct_array_3_sentinel_f32() void;
16425
16426test "struct [3:sentinel]f32" {
16427 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
16428 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16429 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16430 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16431 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16432
16433 var sentinel_index: usize = 3;
16434 _ = &sentinel_index;
16435 const s = c_ret_struct_array_3_sentinel_f32();
16436 try expect(s.a[0] == 8);
16437 try expect(s.a[1] == 9);
16438 try expect(s.a[2] == 10);
16439 try expect(s.a[sentinel_index] == 0x1e1);
16440 c_struct_array_3_sentinel_f32(.{ .a = .{ 11, 12, 13 } }, 14);
16441 c_test_struct_array_3_sentinel_f32();
16442}
16443
16444const Struct_array_4_sentinel_f32 = extern struct {
16445 a: [4:0x1e1]f32,
16446};
16447
16448export fn zig_ret_struct_array_4_sentinel_f32() Struct_array_4_sentinel_f32 {
16449 return .{ .a = .{ 1, 2, 3, 4 } };
16450}
16451export fn zig_struct_array_4_sentinel_f32(s: Struct_array_4_sentinel_f32, i: usize) void {
16452 var sentinel_index: usize = 4;
16453 _ = &sentinel_index;
16454 expect(s.a[0] == 5) catch @panic("test failure");
16455 expect(s.a[1] == 6) catch @panic("test failure");
16456 expect(s.a[2] == 7) catch @panic("test failure");
16457 expect(s.a[3] == 8) catch @panic("test failure");
16458 expect(s.a[sentinel_index] == 0x1e1) catch @panic("test failure");
16459 expect(i == 9) catch @panic("test failure");
16460}
16461
16462extern fn c_ret_struct_array_4_sentinel_f32() Struct_array_4_sentinel_f32;
16463extern fn c_struct_array_4_sentinel_f32(Struct_array_4_sentinel_f32, usize) void;
16464extern fn c_test_struct_array_4_sentinel_f32() void;
16465
16466test "struct [4:sentinel]f32" {
16467 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
16468 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
16469 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
16470 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16471
16472 var sentinel_index: usize = 4;
16473 _ = &sentinel_index;
16474 const s = c_ret_struct_array_4_sentinel_f32();
16475 try expect(s.a[0] == 10);
16476 try expect(s.a[1] == 11);
16477 try expect(s.a[2] == 12);
16478 try expect(s.a[3] == 13);
16479 try expect(s.a[sentinel_index] == 0x1e1);
16480 c_struct_array_4_sentinel_f32(.{ .a = .{ 14, 15, 16, 17 } }, 18);
16481 c_test_struct_array_4_sentinel_f32();
16482}
16483
1628116484const Struct_f32a8 = extern struct {
1628216485 a: f32 align(8),
1628316486};
......@@ -16579,20 +16782,12 @@ const Struct_array_1_f64 = extern struct {
1657916782 a: [1]f64,
1658016783};
1658116784
16582comptime {
16583 skip: {
16584 if (builtin.cpu.arch.isWasm()) break :skip;
16585
16586 _ = struct {
16587 export fn zig_ret_struct_array_1_f64() Struct_array_1_f64 {
16588 return .{ .a = .{1} };
16589 }
16590 export fn zig_struct_array_1_f64(s: Struct_array_1_f64, i: usize) void {
16591 expect(s.a[0] == 2) catch @panic("test failure");
16592 expect(i == 3) catch @panic("test failure");
16593 }
16594 };
16595 }
16785export fn zig_ret_struct_array_1_f64() Struct_array_1_f64 {
16786 return .{ .a = .{1} };
16787}
16788export fn zig_struct_array_1_f64(s: Struct_array_1_f64, i: usize) void {
16789 expect(s.a[0] == 2) catch @panic("test failure");
16790 expect(i == 3) catch @panic("test failure");
1659616791}
1659716792
1659816793extern fn c_ret_struct_array_1_f64() Struct_array_1_f64;
......@@ -16605,8 +16800,6 @@ test "struct [1]f64" {
1660516800 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
1660616801 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
1660716802 if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
16608 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16609 if (builtin.cpu.arch.isWasm()) return error.SkipZigTest;
1661016803
1661116804 const s = c_ret_struct_array_1_f64();
1661216805 try expect(s.a[0] == 4);
......@@ -16750,6 +16943,36 @@ test "struct [5]f64" {
1675016943 c_test_struct_array_5_f64();
1675116944}
1675216945
16946const Union_f64 = extern union {
16947 a: f64,
16948};
16949
16950export fn zig_ret_union_f64() Union_f64 {
16951 return .{ .a = 1 };
16952}
16953export fn zig_union_f64(s: Union_f64, i: usize) void {
16954 expect(s.a == 2) catch @panic("test failure");
16955 expect(i == 3) catch @panic("test failure");
16956}
16957
16958extern fn c_ret_union_f64() Union_f64;
16959extern fn c_union_f64(Union_f64, usize) void;
16960extern fn c_test_union_f64() void;
16961
16962test "union f64" {
16963 if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
16964 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
16965 if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
16966 if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
16967 if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
16968 if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
16969
16970 const s = c_ret_union_f64();
16971 try expect(s.a == 4);
16972 c_union_f64(.{ .a = 5 }, 6);
16973 c_test_union_f64();
16974}
16975
1675316976const Struct_u32_Union_u32_u32u32 = extern struct {
1675416977 a: u32,
1675516978 b: extern union {