From cb1c7319b575372009185c25eac7b29b93ae83f4 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Sat, 25 Apr 2026 09:11:18 -0400 Subject: [PATCH 1/2] llvm: fix aarch64 c abi HFA detection Aggregate types do not count as Homogeneous Aggregates if they have padding gaps between fields or at the end due to field alignments. --- src/codegen/aarch64/abi.zig | 92 +++++++++++++++-------------- src/codegen/llvm/FuncGen.zig | 13 +++-- test/c_abi/cfuncs.c | 108 ++++++++++++++++++++++++++++++----- test/c_abi/main.zig | 78 ++++++++++++++++++++++++- 4 files changed, 227 insertions(+), 64 deletions(-) diff --git a/src/codegen/aarch64/abi.zig b/src/codegen/aarch64/abi.zig index 5b32aded16..369c0813f7 100644 --- a/src/codegen/aarch64/abi.zig +++ b/src/codegen/aarch64/abi.zig @@ -1,5 +1,6 @@ const assert = @import("std").debug.assert; const std = @import("std"); +const InternPool = @import("../../InternPool.zig"); const Type = @import("../../Type.zig"); const Zcu = @import("../../Zcu.zig"); @@ -15,12 +16,10 @@ pub const Class = union(enum) { pub fn classifyType(ty: Type, zcu: *Zcu) Class { assert(ty.hasRuntimeBits(zcu)); - var maybe_float_bits: ?u16 = null; switch (ty.zigTypeTag(zcu)) { .@"struct" => { if (ty.containerLayout(zcu) == .@"packed") return .byval; - const float_count = countFloats(ty, zcu, &maybe_float_bits); - if (float_count <= sret_float_count) return .{ .float_array = float_count }; + if (countFloats(ty, zcu)) |float| return .{ .float_array = float.count }; const bit_size = ty.bitSize(zcu); if (bit_size > 128) return .memory; @@ -29,8 +28,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class { }, .@"union" => { if (ty.containerLayout(zcu) == .@"packed") return .byval; - const float_count = countFloats(ty, zcu, &maybe_float_bits); - if (float_count <= sret_float_count) return .{ .float_array = float_count }; + if (countFloats(ty, zcu)) |float| return .{ .float_array = float.count }; const bit_size = ty.bitSize(zcu); if (bit_size > 128) return .memory; @@ -70,46 +68,52 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class { } } -const sret_float_count = 4; -fn countFloats(ty: Type, zcu: *Zcu, maybe_float_bits: *?u16) u8 { +const CountFloatsResult = struct { + ty: Type, + count: std.math.IntFittingRange(0, max_count), + + const none: CountFloatsResult = .{ .ty = .void, .count = 0 }; + + const max_count = 4; +}; +fn countFloats(ty: Type, zcu: *Zcu) ?CountFloatsResult { const ip = &zcu.intern_pool; - const target = zcu.getTarget(); - const invalid = std.math.maxInt(u8); + if (!ty.hasRuntimeBits(zcu)) return .none; switch (ty.zigTypeTag(zcu)) { .@"union" => { - const union_obj = zcu.typeToUnion(ty).?; - var max_count: u8 = 0; - for (union_obj.field_types.get(ip)) |field_ty| { - const field_count = countFloats(Type.fromInterned(field_ty), zcu, maybe_float_bits); - if (field_count == invalid) return invalid; - if (field_count > max_count) max_count = field_count; - if (max_count > sret_float_count) return invalid; + const loaded_union = zcu.typeToUnion(ty).?; + var result: CountFloatsResult = .none; + for (loaded_union.field_types.get(ip)) |field_ty| { + const float = countFloats(Type.fromInterned(field_ty), zcu) orelse return null; + if (result.ty.toIntern() == .void_type) { + result.ty = float.ty; + } else if (result.ty.bitSize(zcu) != float.ty.bitSize(zcu)) return null; + result.count = @max(result.count, float.count); } - return max_count; + if (ty.abiSize(zcu) != result.ty.abiSize(zcu) * result.count) return null; + return result; }, .@"struct" => { - const fields_len = ty.structFieldCount(zcu); - var count: u8 = 0; - var i: u32 = 0; - while (i < fields_len) : (i += 1) { - const field_ty = ty.fieldType(i, zcu); - const field_count = countFloats(field_ty, zcu, maybe_float_bits); - if (field_count == invalid) return invalid; - count += field_count; - if (count > sret_float_count) return invalid; + var result: CountFloatsResult = .none; + var field_it: InternPool.LoadedStructType.RuntimeOrderIterator = if (zcu.typeToStruct(ty)) |loaded_struct| + loaded_struct.iterateRuntimeOrder(ip) + else + .{ .runtime_order = null, .fields_len = ty.structFieldCount(zcu), .next_index = 0 }; + while (field_it.next()) |field_index| { + if (ty.structFieldOffset(field_index, zcu) != result.ty.abiSize(zcu) * result.count) return null; + const field_ty = ty.fieldType(field_index, zcu); + const float = countFloats(field_ty, zcu) orelse return null; + if (result.ty.toIntern() == .void_type) { + result.ty = float.ty; + } else if (result.ty.bitSize(zcu) != float.ty.bitSize(zcu)) return null; + if (float.count > CountFloatsResult.max_count - result.count) return null; + result.count += float.count; } - return count; + if (ty.abiSize(zcu) != result.ty.abiSize(zcu) * result.count) return null; + return result; }, - .float => { - const float_bits = maybe_float_bits.* orelse { - maybe_float_bits.* = ty.floatBits(target); - return 1; - }; - if (ty.floatBits(target) == float_bits) return 1; - return invalid; - }, - .void => return 0, - else => return invalid, + .float => return .{ .ty = ty, .count = 1 }, + else => return null, } } @@ -117,17 +121,19 @@ pub fn getFloatArrayType(ty: Type, zcu: *Zcu) ?Type { const ip = &zcu.intern_pool; switch (ty.zigTypeTag(zcu)) { .@"union" => { - const union_obj = zcu.typeToUnion(ty).?; - for (union_obj.field_types.get(ip)) |field_ty| { + const loaded_union = zcu.typeToUnion(ty).?; + for (loaded_union.field_types.get(ip)) |field_ty| { if (getFloatArrayType(Type.fromInterned(field_ty), zcu)) |some| return some; } return null; }, .@"struct" => { - const fields_len = ty.structFieldCount(zcu); - var i: u32 = 0; - while (i < fields_len) : (i += 1) { - const field_ty = ty.fieldType(i, zcu); + var field_it: InternPool.LoadedStructType.RuntimeOrderIterator = if (zcu.typeToStruct(ty)) |loaded_struct| + loaded_struct.iterateRuntimeOrder(ip) + else + .{ .runtime_order = null, .fields_len = ty.structFieldCount(zcu), .next_index = 0 }; + while (field_it.next()) |field_index| { + const field_ty = ty.fieldType(field_index, zcu); if (getFloatArrayType(field_ty, zcu)) |some| return some; } return null; diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig index 16029bc788..21022543cb 100644 --- a/src/codegen/llvm/FuncGen.zig +++ b/src/codegen/llvm/FuncGen.zig @@ -6707,17 +6707,18 @@ const ParamTypeIterator = struct { .double_integer => return Lowering{ .i64_array = 2 }, .fields => { it.types_len = 0; - var offset: u64 = 0; - for (0..ty.structFieldCount(zcu)) |field_index| { + var field_it: InternPool.LoadedStructType.RuntimeOrderIterator = if (zcu.typeToStruct(ty)) |loaded_struct| + loaded_struct.iterateRuntimeOrder(&zcu.intern_pool) + else + .{ .runtime_order = null, .fields_len = ty.structFieldCount(zcu), .next_index = 0 }; + while (field_it.next()) |field_index| { const field_ty = ty.fieldType(field_index, zcu); if (!field_ty.hasRuntimeBits(zcu)) continue; - offset = field_ty.abiAlignment(zcu).forward(offset); it.types_buffer[it.types_len] = try it.object.lowerType(field_ty); - it.offsets_buffer[it.types_len] = offset; + it.offsets_buffer[it.types_len] = ty.structFieldOffset(field_index, zcu); it.types_len += 1; - offset += field_ty.abiSize(zcu); } - it.offsets_buffer[it.types_len] = offset; + it.offsets_buffer[it.types_len] = ty.abiSize(zcu); it.llvm_index += it.types_len - 1; return .multiple_llvm_types; }, diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c index 0433423ef3..bd925d58b9 100644 --- a/test/c_abi/cfuncs.c +++ b/test/c_abi/cfuncs.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -209,7 +210,7 @@ struct Struct_u8 zig_ret_struct_u8(void); void zig_struct_u8(struct Struct_u8, size_t); struct Struct_u8 c_ret_struct_u8(void) { - return (struct Struct_u8){ 4 }; + return (struct Struct_u8){ .a = 4 }; } void c_struct_u8(struct Struct_u8 s, size_t i) { @@ -226,7 +227,7 @@ struct Struct_u16 zig_ret_struct_u16(void); void zig_struct_u16(struct Struct_u16, size_t); struct Struct_u16 c_ret_struct_u16(void) { - return (struct Struct_u16){ 10 }; + return (struct Struct_u16){ .a = 10 }; } void c_struct_u16(struct Struct_u16 s, size_t i) { @@ -243,7 +244,7 @@ struct Struct_u32 zig_ret_struct_u32(void); void zig_struct_u32(struct Struct_u32, size_t); struct Struct_u32 c_ret_struct_u32(void) { - return (struct Struct_u32){ 16 }; + return (struct Struct_u32){ .a = 16 }; } void c_struct_u32(struct Struct_u32 s, size_t i) { @@ -260,7 +261,7 @@ struct Struct_u64 zig_ret_struct_u64(void); void zig_struct_u64(struct Struct_u64, size_t); struct Struct_u64 c_ret_struct_u64(void) { - return (struct Struct_u64){ 22 }; + return (struct Struct_u64){ .a = 22 }; } void c_struct_u64(struct Struct_u64 s, size_t i) { @@ -286,7 +287,7 @@ void zig_struct_u64_u64_7(size_t, size_t, size_t, size_t, size_t, size_t, size_t void zig_struct_u64_u64_8(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64, size_t); struct Struct_u64_u64 c_ret_struct_u64_u64(void) { - return (struct Struct_u64_u64){ 21, 22 }; + return (struct Struct_u64_u64){ .a = 21, .b = 22 }; } void c_struct_u64_u64_0(struct Struct_u64_u64 s, size_t i) { @@ -344,7 +345,7 @@ struct Struct_f32 zig_ret_struct_f32(void); void zig_struct_f32(struct Struct_f32); struct Struct_f32 c_ret_struct_f32(void) { - return (struct Struct_f32){ 2.5f }; + return (struct Struct_f32){ .a = 2.5f }; } void c_struct_f32(struct Struct_f32 s) { @@ -360,13 +361,49 @@ struct Struct_f64 zig_ret_struct_f64(void); void zig_struct_f64(struct Struct_f64); struct Struct_f64 c_ret_struct_f64(void) { - return (struct Struct_f64){ 2.5 }; + return (struct Struct_f64){ .a = 2.5 }; } void c_struct_f64(struct Struct_f64 s) { assert_or_panic(s.a == 2.5); } +struct Struct_f32a8 { + alignas(8) float a; +}; + +struct Struct_f32a8 zig_ret_struct_f32a8(void); + +void zig_struct_f32a8(struct Struct_f32a8, float); + +struct Struct_f32a8 c_ret_struct_f32a8(void) { + return (struct Struct_f32a8){ .a = 4.125f }; +} + +void c_struct_f32a8(struct Struct_f32a8 s, float f) { + assert_or_panic(s.a == 5.375f); + assert_or_panic(f == 6.5f); +} + +struct Struct_f32a8_f32a8 { + alignas(8) float a; + alignas(8) float b; +}; + +struct Struct_f32a8_f32a8 zig_ret_struct_f32a8_f32a8(void); + +void zig_struct_f32a8_f32a8(struct Struct_f32a8_f32a8, float); + +struct Struct_f32a8_f32a8 c_ret_struct_f32a8_f32a8(void) { + return (struct Struct_f32a8_f32a8){ .a = 6.625f, .b = 7.875f }; +} + +void c_struct_f32a8_f32a8(struct Struct_f32a8_f32a8 s, float f) { + assert_or_panic(s.a == 8.0625f); + assert_or_panic(s.b == 9.1875f); + assert_or_panic(f == 10.5f); +} + struct Struct_f32f32_f32 { struct { float b, c; @@ -379,7 +416,7 @@ struct Struct_f32f32_f32 zig_ret_struct_f32f32_f32(void); void zig_struct_f32f32_f32(struct Struct_f32f32_f32); struct Struct_f32f32_f32 c_ret_struct_f32f32_f32(void) { - return (struct Struct_f32f32_f32){ { 1.0f, 2.0f }, 3.0f }; + return (struct Struct_f32f32_f32){ .a = { .b = 1.0f, .c = 2.0f }, .d = 3.0f }; } void c_struct_f32f32_f32(struct Struct_f32f32_f32 s) { @@ -400,7 +437,7 @@ struct Struct_f32_f32f32 zig_ret_struct_f32_f32f32(void); void zig_struct_f32_f32f32(struct Struct_f32_f32f32); struct Struct_f32_f32f32 c_ret_struct_f32_f32f32(void) { - return (struct Struct_f32_f32f32){ 1.0f, { 2.0f, 3.0f } }; + return (struct Struct_f32_f32f32){ .a = 1.0f, .b = { .c = 2.0f, .d = 3.0f } }; } void c_struct_f32_f32f32(struct Struct_f32_f32f32 s) { @@ -2870,7 +2907,7 @@ void run_c_tests(void) { { struct Struct_f32 s = zig_ret_struct_f32(); assert_or_panic(s.a == 2.5f); - zig_struct_f32((struct Struct_f32){ 2.5f }); + zig_struct_f32((struct Struct_f32){ .a = 2.5f }); } #endif @@ -2879,17 +2916,62 @@ void run_c_tests(void) { { struct Struct_f64 s = zig_ret_struct_f64(); assert_or_panic(s.a == 2.5); - zig_struct_f64((struct Struct_f64){ 2.5 }); + zig_struct_f64((struct Struct_f64){ .a = 2.5 }); } #endif +#endif +#if !defined(__arm__) +#if !defined(__loongarch__) +#if !defined(__mips64__) +#if !defined(__powerpc__) +#if !defined(ZIG_RISCV32) +#if !defined(__s390x__) +#if !defined(__i386__) + { + struct Struct_f32a8 s = zig_ret_struct_f32a8(); + assert_or_panic(s.a == 1.25f); + zig_struct_f32a8((struct Struct_f32a8){ .a = 2.75f }, 3.5f); + } +#endif +#endif +#endif +#endif +#endif +#endif +#endif + +#if !defined(__arm__) +#if !defined(__loongarch__) +#if !defined(__mips64__) +#if !defined(__powerpc__) +#if !defined(__riscv) +#if !defined(__s390x__) +#if !defined(__i386__) +#if !defined(__x86_64__) + { + struct Struct_f32a8_f32a8 s = zig_ret_struct_f32a8_f32a8(); + assert_or_panic(s.a == 1.25f); + assert_or_panic(s.b == 2.75f); + zig_struct_f32a8_f32a8((struct Struct_f32a8_f32a8){ .a = 3.125f, .b = 4.375f }, 5.5f); + } +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif + +#if !(defined(__arm__) && defined(__SOFTFP__)) #if !defined(__loongarch__) && !defined(__mips64__) { struct Struct_f32f32_f32 s = zig_ret_struct_f32f32_f32(); assert_or_panic(s.a.b == 1.0f); assert_or_panic(s.a.c == 2.0f); assert_or_panic(s.d == 3.0f); - zig_struct_f32f32_f32((struct Struct_f32f32_f32){ { 1.0f, 2.0f }, 3.0f }); + zig_struct_f32f32_f32((struct Struct_f32f32_f32){ .a = { .b = 1.0f, .c = 2.0f }, .d = 3.0f }); } { @@ -2897,7 +2979,7 @@ void run_c_tests(void) { assert_or_panic(s.a == 1.0f); assert_or_panic(s.b.c == 2.0f); assert_or_panic(s.b.d == 3.0f); - zig_struct_f32_f32f32((struct Struct_f32_f32f32){ 1.0f, { 2.0f, 3.0f } }); + zig_struct_f32_f32f32((struct Struct_f32_f32f32){ .a = 1.0f, .b = { .c = 2.0f, .d = 3.0f } }); } #endif #endif diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig index e37696a062..353804e480 100644 --- a/test/c_abi/main.zig +++ b/test/c_abi/main.zig @@ -444,7 +444,7 @@ extern fn c_struct_u64_u64_6(usize, usize, usize, usize, usize, usize, Struct_u6 extern fn c_struct_u64_u64_7(usize, usize, usize, usize, usize, usize, usize, Struct_u64_u64, usize) void; extern fn c_struct_u64_u64_8(usize, usize, usize, usize, usize, usize, usize, usize, Struct_u64_u64, usize) void; -test "C ABI struct u64 u64" { +test "C ABI struct u64, u64" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; @@ -518,6 +518,80 @@ test "C ABI struct f64" { c_struct_f64(.{ .a = 2.5 }); } +const Struct_f32a8 = extern struct { + a: f32 align(8), +}; + +export fn zig_ret_struct_f32a8() Struct_f32a8 { + return .{ .a = 1.25 }; +} + +export fn zig_struct_f32a8(s: Struct_f32a8, f: f32) void { + expect(s.a == 2.75) catch @panic("test failure"); + expect(f == 3.5) catch @panic("test failure"); +} + +extern fn c_ret_struct_f32a8() Struct_f32a8; + +extern fn c_struct_f32a8(Struct_f32a8, f32) void; + +test "C ABI struct f32 align(8)" { + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch == .riscv32) return error.SkipZigTest; + if (builtin.cpu.arch == .s390x) return error.SkipZigTest; + if (builtin.cpu.arch == .x86) return error.SkipZigTest; + + const s = c_ret_struct_f32a8(); + try expect(s.a == 4.125); + c_struct_f32a8(.{ .a = 5.375 }, 6.5); +} + +const Struct_f32a8_f32a8 = extern struct { + a: f32 align(8), + b: f32 align(8), +}; + +comptime { + skip: { + if (builtin.zig_backend == .stage2_x86_64) break :skip; + + _ = struct { + export fn zig_ret_struct_f32a8_f32a8() Struct_f32a8_f32a8 { + return .{ .a = 1.25, .b = 2.75 }; + } + + export fn zig_struct_f32a8_f32a8(s: Struct_f32a8_f32a8, f: f32) void { + expect(s.a == 3.125) catch @panic("test failure"); + expect(s.b == 4.375) catch @panic("test failure"); + expect(f == 5.5) catch @panic("test failure"); + } + }; + } +} + +extern fn c_ret_struct_f32a8_f32a8() Struct_f32a8_f32a8; + +extern fn c_struct_f32a8_f32a8(Struct_f32a8_f32a8, f32) void; + +test "C ABI struct f32 align(8), f32 align(8)" { + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; + if (builtin.cpu.arch == .s390x) return error.SkipZigTest; + if (builtin.cpu.arch == .x86) return error.SkipZigTest; + if (builtin.cpu.arch == .x86_64) return error.SkipZigTest; + + const s = c_ret_struct_f32a8_f32a8(); + try expect(s.a == 6.625); + try expect(s.b == 7.875); + c_struct_f32a8_f32a8(.{ .a = 8.0625, .b = 9.1875 }, 10.5); +} + const Struct_f32f32_f32 = extern struct { a: extern struct { b: f32, c: f32 }, d: f32, @@ -537,7 +611,7 @@ extern fn c_ret_struct_f32f32_f32() Struct_f32f32_f32; extern fn c_struct_f32f32_f32(Struct_f32f32_f32) void; -test "C ABI struct {f32,f32} f32" { +test "C ABI struct {f32, f32}, f32" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest; From 2040f9bfd0ab874c6b7a748b9293ad31c7392459 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Sat, 25 Apr 2026 11:59:21 -0400 Subject: [PATCH 2/2] x86_64: fix c abi of `f32` struct field followed by padding Closes #31864 --- src/codegen/x86_64/CodeGen.zig | 8 +++++--- src/codegen/x86_64/abi.zig | 21 +++++++++++++-------- test/c_abi/cfuncs.c | 2 -- test/c_abi/main.zig | 23 +++++++---------------- 4 files changed, 25 insertions(+), 29 deletions(-) diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig index 72a382fee1..97cee13bb3 100644 --- a/src/codegen/x86_64/CodeGen.zig +++ b/src/codegen/x86_64/CodeGen.zig @@ -181632,9 +181632,11 @@ fn splitType(self: *CodeGen, comptime parts_len: usize, ty: Type) ![parts_len]Ty else => break, }; } else { - var part_sizes: u64 = 0; - for (parts) |part| part_sizes += part.abiSize(zcu); - if (part_sizes == ty.abiSize(zcu)) return parts; + var parts_size: u64 = 0; + for (parts) |part| parts_size += part.abiSize(zcu); + const abi_size = ty.abiSize(zcu); + if (abi_size == parts_size) return parts; + if (classes[classes.len - 1] == .float and abi_size > parts_size and abi_size <= parts_size + 4) return parts; }; return self.fail("TODO implement splitType({d}, {f})", .{ parts_len, ty.fmt(pt) }); } diff --git a/src/codegen/x86_64/abi.zig b/src/codegen/x86_64/abi.zig index 911609b1f3..fcd6e63f92 100644 --- a/src/codegen/x86_64/abi.zig +++ b/src/codegen/x86_64/abi.zig @@ -300,21 +300,26 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont for (result, 0..) |class, i| switch (class) { .memory => return Class.stack, .x87up => if (i == 0 or result[i - 1] != .x87) return Class.stack, - else => continue, + else => {}, }; // "If the size of the aggregate exceeds two eightbytes and the first eight- - // byte isn’t SSE or any other eightbyte isn’t SSEUP, the whole argument + // byte isn't SSE or any other eightbyte isn't SSEUP, the whole argument // is passed in memory." if (ty_size > 16 and (result[0] != .sse or std.mem.indexOfNone(Class, result[1..], &.{ .sseup, .none }) != null)) return Class.stack; // "If SSEUP is not preceded by SSE or SSEUP, it is converted to SSE." - for (&result, 0..) |*item, i| { - if (item.* == .sseup) switch (result[i - 1]) { - .sse, .sseup => continue, - else => item.* = .sse, - }; - } + for (&result, 0..) |*class, i| switch (class.*) { + .sseup => switch (result[i - 1]) { + .sse, .sseup => {}, + else => class.* = .sse, + }, + .float => if (i + 1 < result.len) switch (result[i + 1]) { + .none => {}, + else => class.* = .float_combine, + }, + else => {}, + }; return result; }, .array => { diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c index bd925d58b9..fc708f343e 100644 --- a/test/c_abi/cfuncs.c +++ b/test/c_abi/cfuncs.c @@ -2948,7 +2948,6 @@ void run_c_tests(void) { #if !defined(__riscv) #if !defined(__s390x__) #if !defined(__i386__) -#if !defined(__x86_64__) { struct Struct_f32a8_f32a8 s = zig_ret_struct_f32a8_f32a8(); assert_or_panic(s.a == 1.25f); @@ -2962,7 +2961,6 @@ void run_c_tests(void) { #endif #endif #endif -#endif #if !(defined(__arm__) && defined(__SOFTFP__)) #if !defined(__loongarch__) && !defined(__mips64__) diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig index 353804e480..1f221260b4 100644 --- a/test/c_abi/main.zig +++ b/test/c_abi/main.zig @@ -554,22 +554,14 @@ const Struct_f32a8_f32a8 = extern struct { b: f32 align(8), }; -comptime { - skip: { - if (builtin.zig_backend == .stage2_x86_64) break :skip; +export fn zig_ret_struct_f32a8_f32a8() Struct_f32a8_f32a8 { + return .{ .a = 1.25, .b = 2.75 }; +} - _ = struct { - export fn zig_ret_struct_f32a8_f32a8() Struct_f32a8_f32a8 { - return .{ .a = 1.25, .b = 2.75 }; - } - - export fn zig_struct_f32a8_f32a8(s: Struct_f32a8_f32a8, f: f32) void { - expect(s.a == 3.125) catch @panic("test failure"); - expect(s.b == 4.375) catch @panic("test failure"); - expect(f == 5.5) catch @panic("test failure"); - } - }; - } +export fn zig_struct_f32a8_f32a8(s: Struct_f32a8_f32a8, f: f32) void { + expect(s.a == 3.125) catch @panic("test failure"); + expect(s.b == 4.375) catch @panic("test failure"); + expect(f == 5.5) catch @panic("test failure"); } extern fn c_ret_struct_f32a8_f32a8() Struct_f32a8_f32a8; @@ -584,7 +576,6 @@ test "C ABI struct f32 align(8), f32 align(8)" { if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; - if (builtin.cpu.arch == .x86_64) return error.SkipZigTest; const s = c_ret_struct_f32a8_f32a8(); try expect(s.a == 6.625);