mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-26 13:01:34 +03:00
Merge pull request 'fix more c abi bugs' (#32071) from c-abi-padding into master
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/32071 Reviewed-by: Andrew Kelley <andrew@ziglang.org>
This commit is contained in:
+49
-43
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
},
|
||||
|
||||
@@ -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) });
|
||||
}
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
+93
-13
@@ -1,5 +1,6 @@
|
||||
#include <complex.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdalign.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -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,60 @@ 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__)
|
||||
{
|
||||
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
|
||||
|
||||
#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 +2977,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
|
||||
|
||||
+67
-2
@@ -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,71 @@ 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),
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
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 +602,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;
|
||||
|
||||
Reference in New Issue
Block a user