| author | |
| committer | |
| log | f0a7e3ccae45ce7d09038204c16155d5b98ad560 |
| tree | c165ed76e2432b7753334bb69bc1cfc1ac69be88 |
| parent | e7d74e49b0dd91e679aa9063311a4513339cedd0 |
| parent | 2040f9bfd0ab874c6b7a748b9293ad31c7392459 |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/32071
Reviewed-by: Andrew Kelley <andrew@ziglang.org>6 files changed, 234 insertions(+), 75 deletions(-)
src/codegen/aarch64/abi.zig+49-43| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | const assert = @import("std").debug.assert; | 1 | const assert = @import("std").debug.assert; |
| 2 | const std = @import("std"); | 2 | const std = @import("std"); |
| 3 | const InternPool = @import("../../InternPool.zig"); | ||
| 3 | const Type = @import("../../Type.zig"); | 4 | const Type = @import("../../Type.zig"); |
| 4 | const Zcu = @import("../../Zcu.zig"); | 5 | const Zcu = @import("../../Zcu.zig"); |
| 5 | 6 | ||
| ... | @@ -15,12 +16,10 @@ pub const Class = union(enum) { | ... | @@ -15,12 +16,10 @@ pub const Class = union(enum) { |
| 15 | pub fn classifyType(ty: Type, zcu: *Zcu) Class { | 16 | pub fn classifyType(ty: Type, zcu: *Zcu) Class { |
| 16 | assert(ty.hasRuntimeBits(zcu)); | 17 | assert(ty.hasRuntimeBits(zcu)); |
| 17 | 18 | ||
| 18 | var maybe_float_bits: ?u16 = null; | ||
| 19 | switch (ty.zigTypeTag(zcu)) { | 19 | switch (ty.zigTypeTag(zcu)) { |
| 20 | .@"struct" => { | 20 | .@"struct" => { |
| 21 | if (ty.containerLayout(zcu) == .@"packed") return .byval; | 21 | if (ty.containerLayout(zcu) == .@"packed") return .byval; |
| 22 | const float_count = countFloats(ty, zcu, &maybe_float_bits); | 22 | if (countFloats(ty, zcu)) |float| return .{ .float_array = float.count }; |
| 23 | if (float_count <= sret_float_count) return .{ .float_array = float_count }; | ||
| 24 | 23 | ||
| 25 | const bit_size = ty.bitSize(zcu); | 24 | const bit_size = ty.bitSize(zcu); |
| 26 | if (bit_size > 128) return .memory; | 25 | if (bit_size > 128) return .memory; |
| ... | @@ -29,8 +28,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class { | ... | @@ -29,8 +28,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class { |
| 29 | }, | 28 | }, |
| 30 | .@"union" => { | 29 | .@"union" => { |
| 31 | if (ty.containerLayout(zcu) == .@"packed") return .byval; | 30 | if (ty.containerLayout(zcu) == .@"packed") return .byval; |
| 32 | const float_count = countFloats(ty, zcu, &maybe_float_bits); | 31 | if (countFloats(ty, zcu)) |float| return .{ .float_array = float.count }; |
| 33 | if (float_count <= sret_float_count) return .{ .float_array = float_count }; | ||
| 34 | 32 | ||
| 35 | const bit_size = ty.bitSize(zcu); | 33 | const bit_size = ty.bitSize(zcu); |
| 36 | if (bit_size > 128) return .memory; | 34 | if (bit_size > 128) return .memory; |
| ... | @@ -70,46 +68,52 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class { | ... | @@ -70,46 +68,52 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class { |
| 70 | } | 68 | } |
| 71 | } | 69 | } |
| 72 | 70 | ||
| 73 | const sret_float_count = 4; | 71 | const CountFloatsResult = struct { |
| 74 | fn countFloats(ty: Type, zcu: *Zcu, maybe_float_bits: *?u16) u8 { | 72 | ty: Type, |
| 73 | count: std.math.IntFittingRange(0, max_count), | ||
| 74 | |||
| 75 | const none: CountFloatsResult = .{ .ty = .void, .count = 0 }; | ||
| 76 | |||
| 77 | const max_count = 4; | ||
| 78 | }; | ||
| 79 | fn countFloats(ty: Type, zcu: *Zcu) ?CountFloatsResult { | ||
| 75 | const ip = &zcu.intern_pool; | 80 | const ip = &zcu.intern_pool; |
| 76 | const target = zcu.getTarget(); | 81 | if (!ty.hasRuntimeBits(zcu)) return .none; |
| 77 | const invalid = std.math.maxInt(u8); | ||
| 78 | switch (ty.zigTypeTag(zcu)) { | 82 | switch (ty.zigTypeTag(zcu)) { |
| 79 | .@"union" => { | 83 | .@"union" => { |
| 80 | const union_obj = zcu.typeToUnion(ty).?; | 84 | const loaded_union = zcu.typeToUnion(ty).?; |
| 81 | var max_count: u8 = 0; | 85 | var result: CountFloatsResult = .none; |
| 82 | for (union_obj.field_types.get(ip)) |field_ty| { | 86 | for (loaded_union.field_types.get(ip)) |field_ty| { |
| 83 | const field_count = countFloats(Type.fromInterned(field_ty), zcu, maybe_float_bits); | 87 | const float = countFloats(Type.fromInterned(field_ty), zcu) orelse return null; |
| 84 | if (field_count == invalid) return invalid; | 88 | if (result.ty.toIntern() == .void_type) { |
| 85 | if (field_count > max_count) max_count = field_count; | 89 | result.ty = float.ty; |
| 86 | if (max_count > sret_float_count) return invalid; | 90 | } else if (result.ty.bitSize(zcu) != float.ty.bitSize(zcu)) return null; |
| 91 | result.count = @max(result.count, float.count); | ||
| 87 | } | 92 | } |
| 88 | return max_count; | 93 | if (ty.abiSize(zcu) != result.ty.abiSize(zcu) * result.count) return null; |
| 94 | return result; | ||
| 89 | }, | 95 | }, |
| 90 | .@"struct" => { | 96 | .@"struct" => { |
| 91 | const fields_len = ty.structFieldCount(zcu); | 97 | var result: CountFloatsResult = .none; |
| 92 | var count: u8 = 0; | 98 | var field_it: InternPool.LoadedStructType.RuntimeOrderIterator = if (zcu.typeToStruct(ty)) |loaded_struct| |
| 93 | var i: u32 = 0; | 99 | loaded_struct.iterateRuntimeOrder(ip) |
| 94 | while (i < fields_len) : (i += 1) { | 100 | else |
| 95 | const field_ty = ty.fieldType(i, zcu); | 101 | .{ .runtime_order = null, .fields_len = ty.structFieldCount(zcu), .next_index = 0 }; |
| 96 | const field_count = countFloats(field_ty, zcu, maybe_float_bits); | 102 | while (field_it.next()) |field_index| { |
| 97 | if (field_count == invalid) return invalid; | 103 | if (ty.structFieldOffset(field_index, zcu) != result.ty.abiSize(zcu) * result.count) return null; |
| 98 | count += field_count; | 104 | const field_ty = ty.fieldType(field_index, zcu); |
| 99 | if (count > sret_float_count) return invalid; | 105 | const float = countFloats(field_ty, zcu) orelse return null; |
| 106 | if (result.ty.toIntern() == .void_type) { | ||
| 107 | result.ty = float.ty; | ||
| 108 | } else if (result.ty.bitSize(zcu) != float.ty.bitSize(zcu)) return null; | ||
| 109 | if (float.count > CountFloatsResult.max_count - result.count) return null; | ||
| 110 | result.count += float.count; | ||
| 100 | } | 111 | } |
| 101 | return count; | 112 | if (ty.abiSize(zcu) != result.ty.abiSize(zcu) * result.count) return null; |
| 113 | return result; | ||
| 102 | }, | 114 | }, |
| 103 | .float => { | 115 | .float => return .{ .ty = ty, .count = 1 }, |
| 104 | const float_bits = maybe_float_bits.* orelse { | 116 | else => return null, |
| 105 | maybe_float_bits.* = ty.floatBits(target); | ||
| 106 | return 1; | ||
| 107 | }; | ||
| 108 | if (ty.floatBits(target) == float_bits) return 1; | ||
| 109 | return invalid; | ||
| 110 | }, | ||
| 111 | .void => return 0, | ||
| 112 | else => return invalid, | ||
| 113 | } | 117 | } |
| 114 | } | 118 | } |
| 115 | 119 | ||
| ... | @@ -117,17 +121,19 @@ pub fn getFloatArrayType(ty: Type, zcu: *Zcu) ?Type { | ... | @@ -117,17 +121,19 @@ pub fn getFloatArrayType(ty: Type, zcu: *Zcu) ?Type { |
| 117 | const ip = &zcu.intern_pool; | 121 | const ip = &zcu.intern_pool; |
| 118 | switch (ty.zigTypeTag(zcu)) { | 122 | switch (ty.zigTypeTag(zcu)) { |
| 119 | .@"union" => { | 123 | .@"union" => { |
| 120 | const union_obj = zcu.typeToUnion(ty).?; | 124 | const loaded_union = zcu.typeToUnion(ty).?; |
| 121 | for (union_obj.field_types.get(ip)) |field_ty| { | 125 | for (loaded_union.field_types.get(ip)) |field_ty| { |
| 122 | if (getFloatArrayType(Type.fromInterned(field_ty), zcu)) |some| return some; | 126 | if (getFloatArrayType(Type.fromInterned(field_ty), zcu)) |some| return some; |
| 123 | } | 127 | } |
| 124 | return null; | 128 | return null; |
| 125 | }, | 129 | }, |
| 126 | .@"struct" => { | 130 | .@"struct" => { |
| 127 | const fields_len = ty.structFieldCount(zcu); | 131 | var field_it: InternPool.LoadedStructType.RuntimeOrderIterator = if (zcu.typeToStruct(ty)) |loaded_struct| |
| 128 | var i: u32 = 0; | 132 | loaded_struct.iterateRuntimeOrder(ip) |
| 129 | while (i < fields_len) : (i += 1) { | 133 | else |
| 130 | const field_ty = ty.fieldType(i, zcu); | 134 | .{ .runtime_order = null, .fields_len = ty.structFieldCount(zcu), .next_index = 0 }; |
| 135 | while (field_it.next()) |field_index| { | ||
| 136 | const field_ty = ty.fieldType(field_index, zcu); | ||
| 131 | if (getFloatArrayType(field_ty, zcu)) |some| return some; | 137 | if (getFloatArrayType(field_ty, zcu)) |some| return some; |
| 132 | } | 138 | } |
| 133 | return null; | 139 | return null; |
src/codegen/llvm/FuncGen.zig+7-6| ... | @@ -6707,17 +6707,18 @@ const ParamTypeIterator = struct { | ... | @@ -6707,17 +6707,18 @@ const ParamTypeIterator = struct { |
| 6707 | .double_integer => return Lowering{ .i64_array = 2 }, | 6707 | .double_integer => return Lowering{ .i64_array = 2 }, |
| 6708 | .fields => { | 6708 | .fields => { |
| 6709 | it.types_len = 0; | 6709 | it.types_len = 0; |
| 6710 | var offset: u64 = 0; | 6710 | var field_it: InternPool.LoadedStructType.RuntimeOrderIterator = if (zcu.typeToStruct(ty)) |loaded_struct| |
| 6711 | for (0..ty.structFieldCount(zcu)) |field_index| { | 6711 | loaded_struct.iterateRuntimeOrder(&zcu.intern_pool) |
| 6712 | else | ||
| 6713 | .{ .runtime_order = null, .fields_len = ty.structFieldCount(zcu), .next_index = 0 }; | ||
| 6714 | while (field_it.next()) |field_index| { | ||
| 6712 | const field_ty = ty.fieldType(field_index, zcu); | 6715 | const field_ty = ty.fieldType(field_index, zcu); |
| 6713 | if (!field_ty.hasRuntimeBits(zcu)) continue; | 6716 | if (!field_ty.hasRuntimeBits(zcu)) continue; |
| 6714 | offset = field_ty.abiAlignment(zcu).forward(offset); | ||
| 6715 | it.types_buffer[it.types_len] = try it.object.lowerType(field_ty); | 6717 | it.types_buffer[it.types_len] = try it.object.lowerType(field_ty); |
| 6716 | it.offsets_buffer[it.types_len] = offset; | 6718 | it.offsets_buffer[it.types_len] = ty.structFieldOffset(field_index, zcu); |
| 6717 | it.types_len += 1; | 6719 | it.types_len += 1; |
| 6718 | offset += field_ty.abiSize(zcu); | ||
| 6719 | } | 6720 | } |
| 6720 | it.offsets_buffer[it.types_len] = offset; | 6721 | it.offsets_buffer[it.types_len] = ty.abiSize(zcu); |
| 6721 | it.llvm_index += it.types_len - 1; | 6722 | it.llvm_index += it.types_len - 1; |
| 6722 | return .multiple_llvm_types; | 6723 | return .multiple_llvm_types; |
| 6723 | }, | 6724 | }, |
src/codegen/x86_64/CodeGen.zig+5-3| ... | @@ -181632,9 +181632,11 @@ fn splitType(self: *CodeGen, comptime parts_len: usize, ty: Type) ![parts_len]Ty | ... | @@ -181632,9 +181632,11 @@ fn splitType(self: *CodeGen, comptime parts_len: usize, ty: Type) ![parts_len]Ty |
| 181632 | else => break, | 181632 | else => break, |
| 181633 | }; | 181633 | }; |
| 181634 | } else { | 181634 | } else { |
| 181635 | var part_sizes: u64 = 0; | 181635 | var parts_size: u64 = 0; |
| 181636 | for (parts) |part| part_sizes += part.abiSize(zcu); | 181636 | for (parts) |part| parts_size += part.abiSize(zcu); |
| 181637 | if (part_sizes == ty.abiSize(zcu)) return parts; | 181637 | const abi_size = ty.abiSize(zcu); |
| 181638 | if (abi_size == parts_size) return parts; | ||
| 181639 | if (classes[classes.len - 1] == .float and abi_size > parts_size and abi_size <= parts_size + 4) return parts; | ||
| 181638 | }; | 181640 | }; |
| 181639 | return self.fail("TODO implement splitType({d}, {f})", .{ parts_len, ty.fmt(pt) }); | 181641 | return self.fail("TODO implement splitType({d}, {f})", .{ parts_len, ty.fmt(pt) }); |
| 181640 | } | 181642 | } |
src/codegen/x86_64/abi.zig+13-8| ... | @@ -300,21 +300,26 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont | ... | @@ -300,21 +300,26 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont |
| 300 | for (result, 0..) |class, i| switch (class) { | 300 | for (result, 0..) |class, i| switch (class) { |
| 301 | .memory => return Class.stack, | 301 | .memory => return Class.stack, |
| 302 | .x87up => if (i == 0 or result[i - 1] != .x87) return Class.stack, | 302 | .x87up => if (i == 0 or result[i - 1] != .x87) return Class.stack, |
| 303 | else => continue, | 303 | else => {}, |
| 304 | }; | 304 | }; |
| 305 | // "If the size of the aggregate exceeds two eightbytes and the first eight- | 305 | // "If the size of the aggregate exceeds two eightbytes and the first eight- |
| 306 | // byte isn’t SSE or any other eightbyte isn’t SSEUP, the whole argument | 306 | // byte isn't SSE or any other eightbyte isn't SSEUP, the whole argument |
| 307 | // is passed in memory." | 307 | // is passed in memory." |
| 308 | if (ty_size > 16 and (result[0] != .sse or | 308 | if (ty_size > 16 and (result[0] != .sse or |
| 309 | std.mem.indexOfNone(Class, result[1..], &.{ .sseup, .none }) != null)) return Class.stack; | 309 | std.mem.indexOfNone(Class, result[1..], &.{ .sseup, .none }) != null)) return Class.stack; |
| 310 | 310 | ||
| 311 | // "If SSEUP is not preceded by SSE or SSEUP, it is converted to SSE." | 311 | // "If SSEUP is not preceded by SSE or SSEUP, it is converted to SSE." |
| 312 | for (&result, 0..) |*item, i| { | 312 | for (&result, 0..) |*class, i| switch (class.*) { |
| 313 | if (item.* == .sseup) switch (result[i - 1]) { | 313 | .sseup => switch (result[i - 1]) { |
| 314 | .sse, .sseup => continue, | 314 | .sse, .sseup => {}, |
| 315 | else => item.* = .sse, | 315 | else => class.* = .sse, |
| 316 | }; | 316 | }, |
| 317 | } | 317 | .float => if (i + 1 < result.len) switch (result[i + 1]) { |
| 318 | .none => {}, | ||
| 319 | else => class.* = .float_combine, | ||
| 320 | }, | ||
| 321 | else => {}, | ||
| 322 | }; | ||
| 318 | return result; | 323 | return result; |
| 319 | }, | 324 | }, |
| 320 | .array => { | 325 | .array => { |
test/c_abi/cfuncs.c+93-13| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | #include <complex.h> | 1 | #include <complex.h> |
| 2 | #include <inttypes.h> | 2 | #include <inttypes.h> |
| 3 | #include <stdalign.h> | ||
| 3 | #include <stdbool.h> | 4 | #include <stdbool.h> |
| 4 | #include <stdlib.h> | 5 | #include <stdlib.h> |
| 5 | #include <string.h> | 6 | #include <string.h> |
| ... | @@ -209,7 +210,7 @@ struct Struct_u8 zig_ret_struct_u8(void); | ... | @@ -209,7 +210,7 @@ struct Struct_u8 zig_ret_struct_u8(void); |
| 209 | void zig_struct_u8(struct Struct_u8, size_t); | 210 | void zig_struct_u8(struct Struct_u8, size_t); |
| 210 | 211 | ||
| 211 | struct Struct_u8 c_ret_struct_u8(void) { | 212 | struct Struct_u8 c_ret_struct_u8(void) { |
| 212 | return (struct Struct_u8){ 4 }; | 213 | return (struct Struct_u8){ .a = 4 }; |
| 213 | } | 214 | } |
| 214 | 215 | ||
| 215 | void c_struct_u8(struct Struct_u8 s, size_t i) { | 216 | void c_struct_u8(struct Struct_u8 s, size_t i) { |
| ... | @@ -226,7 +227,7 @@ struct Struct_u16 zig_ret_struct_u16(void); | ... | @@ -226,7 +227,7 @@ struct Struct_u16 zig_ret_struct_u16(void); |
| 226 | void zig_struct_u16(struct Struct_u16, size_t); | 227 | void zig_struct_u16(struct Struct_u16, size_t); |
| 227 | 228 | ||
| 228 | struct Struct_u16 c_ret_struct_u16(void) { | 229 | struct Struct_u16 c_ret_struct_u16(void) { |
| 229 | return (struct Struct_u16){ 10 }; | 230 | return (struct Struct_u16){ .a = 10 }; |
| 230 | } | 231 | } |
| 231 | 232 | ||
| 232 | void c_struct_u16(struct Struct_u16 s, size_t i) { | 233 | void c_struct_u16(struct Struct_u16 s, size_t i) { |
| ... | @@ -243,7 +244,7 @@ struct Struct_u32 zig_ret_struct_u32(void); | ... | @@ -243,7 +244,7 @@ struct Struct_u32 zig_ret_struct_u32(void); |
| 243 | void zig_struct_u32(struct Struct_u32, size_t); | 244 | void zig_struct_u32(struct Struct_u32, size_t); |
| 244 | 245 | ||
| 245 | struct Struct_u32 c_ret_struct_u32(void) { | 246 | struct Struct_u32 c_ret_struct_u32(void) { |
| 246 | return (struct Struct_u32){ 16 }; | 247 | return (struct Struct_u32){ .a = 16 }; |
| 247 | } | 248 | } |
| 248 | 249 | ||
| 249 | void c_struct_u32(struct Struct_u32 s, size_t i) { | 250 | void c_struct_u32(struct Struct_u32 s, size_t i) { |
| ... | @@ -260,7 +261,7 @@ struct Struct_u64 zig_ret_struct_u64(void); | ... | @@ -260,7 +261,7 @@ struct Struct_u64 zig_ret_struct_u64(void); |
| 260 | void zig_struct_u64(struct Struct_u64, size_t); | 261 | void zig_struct_u64(struct Struct_u64, size_t); |
| 261 | 262 | ||
| 262 | struct Struct_u64 c_ret_struct_u64(void) { | 263 | struct Struct_u64 c_ret_struct_u64(void) { |
| 263 | return (struct Struct_u64){ 22 }; | 264 | return (struct Struct_u64){ .a = 22 }; |
| 264 | } | 265 | } |
| 265 | 266 | ||
| 266 | void c_struct_u64(struct Struct_u64 s, size_t i) { | 267 | 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 | ... | @@ -286,7 +287,7 @@ void zig_struct_u64_u64_7(size_t, size_t, size_t, size_t, size_t, size_t, size_t |
| 286 | 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); | 287 | 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); |
| 287 | 288 | ||
| 288 | struct Struct_u64_u64 c_ret_struct_u64_u64(void) { | 289 | struct Struct_u64_u64 c_ret_struct_u64_u64(void) { |
| 289 | return (struct Struct_u64_u64){ 21, 22 }; | 290 | return (struct Struct_u64_u64){ .a = 21, .b = 22 }; |
| 290 | } | 291 | } |
| 291 | 292 | ||
| 292 | void c_struct_u64_u64_0(struct Struct_u64_u64 s, size_t i) { | 293 | 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); | ... | @@ -344,7 +345,7 @@ struct Struct_f32 zig_ret_struct_f32(void); |
| 344 | void zig_struct_f32(struct Struct_f32); | 345 | void zig_struct_f32(struct Struct_f32); |
| 345 | 346 | ||
| 346 | struct Struct_f32 c_ret_struct_f32(void) { | 347 | struct Struct_f32 c_ret_struct_f32(void) { |
| 347 | return (struct Struct_f32){ 2.5f }; | 348 | return (struct Struct_f32){ .a = 2.5f }; |
| 348 | } | 349 | } |
| 349 | 350 | ||
| 350 | void c_struct_f32(struct Struct_f32 s) { | 351 | void c_struct_f32(struct Struct_f32 s) { |
| ... | @@ -360,13 +361,49 @@ struct Struct_f64 zig_ret_struct_f64(void); | ... | @@ -360,13 +361,49 @@ struct Struct_f64 zig_ret_struct_f64(void); |
| 360 | void zig_struct_f64(struct Struct_f64); | 361 | void zig_struct_f64(struct Struct_f64); |
| 361 | 362 | ||
| 362 | struct Struct_f64 c_ret_struct_f64(void) { | 363 | struct Struct_f64 c_ret_struct_f64(void) { |
| 363 | return (struct Struct_f64){ 2.5 }; | 364 | return (struct Struct_f64){ .a = 2.5 }; |
| 364 | } | 365 | } |
| 365 | 366 | ||
| 366 | void c_struct_f64(struct Struct_f64 s) { | 367 | void c_struct_f64(struct Struct_f64 s) { |
| 367 | assert_or_panic(s.a == 2.5); | 368 | assert_or_panic(s.a == 2.5); |
| 368 | } | 369 | } |
| 369 | 370 | ||
| 371 | struct Struct_f32a8 { | ||
| 372 | alignas(8) float a; | ||
| 373 | }; | ||
| 374 | |||
| 375 | struct Struct_f32a8 zig_ret_struct_f32a8(void); | ||
| 376 | |||
| 377 | void zig_struct_f32a8(struct Struct_f32a8, float); | ||
| 378 | |||
| 379 | struct Struct_f32a8 c_ret_struct_f32a8(void) { | ||
| 380 | return (struct Struct_f32a8){ .a = 4.125f }; | ||
| 381 | } | ||
| 382 | |||
| 383 | void c_struct_f32a8(struct Struct_f32a8 s, float f) { | ||
| 384 | assert_or_panic(s.a == 5.375f); | ||
| 385 | assert_or_panic(f == 6.5f); | ||
| 386 | } | ||
| 387 | |||
| 388 | struct Struct_f32a8_f32a8 { | ||
| 389 | alignas(8) float a; | ||
| 390 | alignas(8) float b; | ||
| 391 | }; | ||
| 392 | |||
| 393 | struct Struct_f32a8_f32a8 zig_ret_struct_f32a8_f32a8(void); | ||
| 394 | |||
| 395 | void zig_struct_f32a8_f32a8(struct Struct_f32a8_f32a8, float); | ||
| 396 | |||
| 397 | struct Struct_f32a8_f32a8 c_ret_struct_f32a8_f32a8(void) { | ||
| 398 | return (struct Struct_f32a8_f32a8){ .a = 6.625f, .b = 7.875f }; | ||
| 399 | } | ||
| 400 | |||
| 401 | void c_struct_f32a8_f32a8(struct Struct_f32a8_f32a8 s, float f) { | ||
| 402 | assert_or_panic(s.a == 8.0625f); | ||
| 403 | assert_or_panic(s.b == 9.1875f); | ||
| 404 | assert_or_panic(f == 10.5f); | ||
| 405 | } | ||
| 406 | |||
| 370 | struct Struct_f32f32_f32 { | 407 | struct Struct_f32f32_f32 { |
| 371 | struct { | 408 | struct { |
| 372 | float b, c; | 409 | float b, c; |
| ... | @@ -379,7 +416,7 @@ struct Struct_f32f32_f32 zig_ret_struct_f32f32_f32(void); | ... | @@ -379,7 +416,7 @@ struct Struct_f32f32_f32 zig_ret_struct_f32f32_f32(void); |
| 379 | void zig_struct_f32f32_f32(struct Struct_f32f32_f32); | 416 | void zig_struct_f32f32_f32(struct Struct_f32f32_f32); |
| 380 | 417 | ||
| 381 | struct Struct_f32f32_f32 c_ret_struct_f32f32_f32(void) { | 418 | struct Struct_f32f32_f32 c_ret_struct_f32f32_f32(void) { |
| 382 | return (struct Struct_f32f32_f32){ { 1.0f, 2.0f }, 3.0f }; | 419 | return (struct Struct_f32f32_f32){ .a = { .b = 1.0f, .c = 2.0f }, .d = 3.0f }; |
| 383 | } | 420 | } |
| 384 | 421 | ||
| 385 | void c_struct_f32f32_f32(struct Struct_f32f32_f32 s) { | 422 | void c_struct_f32f32_f32(struct Struct_f32f32_f32 s) { |
| ... | @@ -400,7 +437,7 @@ struct Struct_f32_f32f32 zig_ret_struct_f32_f32f32(void); | ... | @@ -400,7 +437,7 @@ struct Struct_f32_f32f32 zig_ret_struct_f32_f32f32(void); |
| 400 | void zig_struct_f32_f32f32(struct Struct_f32_f32f32); | 437 | void zig_struct_f32_f32f32(struct Struct_f32_f32f32); |
| 401 | 438 | ||
| 402 | struct Struct_f32_f32f32 c_ret_struct_f32_f32f32(void) { | 439 | struct Struct_f32_f32f32 c_ret_struct_f32_f32f32(void) { |
| 403 | return (struct Struct_f32_f32f32){ 1.0f, { 2.0f, 3.0f } }; | 440 | return (struct Struct_f32_f32f32){ .a = 1.0f, .b = { .c = 2.0f, .d = 3.0f } }; |
| 404 | } | 441 | } |
| 405 | 442 | ||
| 406 | void c_struct_f32_f32f32(struct Struct_f32_f32f32 s) { | 443 | void c_struct_f32_f32f32(struct Struct_f32_f32f32 s) { |
| ... | @@ -2870,7 +2907,7 @@ void run_c_tests(void) { | ... | @@ -2870,7 +2907,7 @@ void run_c_tests(void) { |
| 2870 | { | 2907 | { |
| 2871 | struct Struct_f32 s = zig_ret_struct_f32(); | 2908 | struct Struct_f32 s = zig_ret_struct_f32(); |
| 2872 | assert_or_panic(s.a == 2.5f); | 2909 | assert_or_panic(s.a == 2.5f); |
| 2873 | zig_struct_f32((struct Struct_f32){ 2.5f }); | 2910 | zig_struct_f32((struct Struct_f32){ .a = 2.5f }); |
| 2874 | } | 2911 | } |
| 2875 | #endif | 2912 | #endif |
| 2876 | 2913 | ||
| ... | @@ -2879,17 +2916,60 @@ void run_c_tests(void) { | ... | @@ -2879,17 +2916,60 @@ void run_c_tests(void) { |
| 2879 | { | 2916 | { |
| 2880 | struct Struct_f64 s = zig_ret_struct_f64(); | 2917 | struct Struct_f64 s = zig_ret_struct_f64(); |
| 2881 | assert_or_panic(s.a == 2.5); | 2918 | assert_or_panic(s.a == 2.5); |
| 2882 | zig_struct_f64((struct Struct_f64){ 2.5 }); | 2919 | zig_struct_f64((struct Struct_f64){ .a = 2.5 }); |
| 2883 | } | 2920 | } |
| 2884 | #endif | 2921 | #endif |
| 2922 | #endif | ||
| 2885 | 2923 | ||
| 2924 | #if !defined(__arm__) | ||
| 2925 | #if !defined(__loongarch__) | ||
| 2926 | #if !defined(__mips64__) | ||
| 2927 | #if !defined(__powerpc__) | ||
| 2928 | #if !defined(ZIG_RISCV32) | ||
| 2929 | #if !defined(__s390x__) | ||
| 2930 | #if !defined(__i386__) | ||
| 2931 | { | ||
| 2932 | struct Struct_f32a8 s = zig_ret_struct_f32a8(); | ||
| 2933 | assert_or_panic(s.a == 1.25f); | ||
| 2934 | zig_struct_f32a8((struct Struct_f32a8){ .a = 2.75f }, 3.5f); | ||
| 2935 | } | ||
| 2936 | #endif | ||
| 2937 | #endif | ||
| 2938 | #endif | ||
| 2939 | #endif | ||
| 2940 | #endif | ||
| 2941 | #endif | ||
| 2942 | #endif | ||
| 2943 | |||
| 2944 | #if !defined(__arm__) | ||
| 2945 | #if !defined(__loongarch__) | ||
| 2946 | #if !defined(__mips64__) | ||
| 2947 | #if !defined(__powerpc__) | ||
| 2948 | #if !defined(__riscv) | ||
| 2949 | #if !defined(__s390x__) | ||
| 2950 | #if !defined(__i386__) | ||
| 2951 | { | ||
| 2952 | struct Struct_f32a8_f32a8 s = zig_ret_struct_f32a8_f32a8(); | ||
| 2953 | assert_or_panic(s.a == 1.25f); | ||
| 2954 | assert_or_panic(s.b == 2.75f); | ||
| 2955 | zig_struct_f32a8_f32a8((struct Struct_f32a8_f32a8){ .a = 3.125f, .b = 4.375f }, 5.5f); | ||
| 2956 | } | ||
| 2957 | #endif | ||
| 2958 | #endif | ||
| 2959 | #endif | ||
| 2960 | #endif | ||
| 2961 | #endif | ||
| 2962 | #endif | ||
| 2963 | #endif | ||
| 2964 | |||
| 2965 | #if !(defined(__arm__) && defined(__SOFTFP__)) | ||
| 2886 | #if !defined(__loongarch__) && !defined(__mips64__) | 2966 | #if !defined(__loongarch__) && !defined(__mips64__) |
| 2887 | { | 2967 | { |
| 2888 | struct Struct_f32f32_f32 s = zig_ret_struct_f32f32_f32(); | 2968 | struct Struct_f32f32_f32 s = zig_ret_struct_f32f32_f32(); |
| 2889 | assert_or_panic(s.a.b == 1.0f); | 2969 | assert_or_panic(s.a.b == 1.0f); |
| 2890 | assert_or_panic(s.a.c == 2.0f); | 2970 | assert_or_panic(s.a.c == 2.0f); |
| 2891 | assert_or_panic(s.d == 3.0f); | 2971 | assert_or_panic(s.d == 3.0f); |
| 2892 | zig_struct_f32f32_f32((struct Struct_f32f32_f32){ { 1.0f, 2.0f }, 3.0f }); | 2972 | zig_struct_f32f32_f32((struct Struct_f32f32_f32){ .a = { .b = 1.0f, .c = 2.0f }, .d = 3.0f }); |
| 2893 | } | 2973 | } |
| 2894 | 2974 | ||
| 2895 | { | 2975 | { |
| ... | @@ -2897,7 +2977,7 @@ void run_c_tests(void) { | ... | @@ -2897,7 +2977,7 @@ void run_c_tests(void) { |
| 2897 | assert_or_panic(s.a == 1.0f); | 2977 | assert_or_panic(s.a == 1.0f); |
| 2898 | assert_or_panic(s.b.c == 2.0f); | 2978 | assert_or_panic(s.b.c == 2.0f); |
| 2899 | assert_or_panic(s.b.d == 3.0f); | 2979 | assert_or_panic(s.b.d == 3.0f); |
| 2900 | zig_struct_f32_f32f32((struct Struct_f32_f32f32){ 1.0f, { 2.0f, 3.0f } }); | 2980 | zig_struct_f32_f32f32((struct Struct_f32_f32f32){ .a = 1.0f, .b = { .c = 2.0f, .d = 3.0f } }); |
| 2901 | } | 2981 | } |
| 2902 | #endif | 2982 | #endif |
| 2903 | #endif | 2983 | #endif |
test/c_abi/main.zig+67-2| ... | @@ -444,7 +444,7 @@ extern fn c_struct_u64_u64_6(usize, usize, usize, usize, usize, usize, Struct_u6 | ... | @@ -444,7 +444,7 @@ extern fn c_struct_u64_u64_6(usize, usize, usize, usize, usize, usize, Struct_u6 |
| 444 | extern fn c_struct_u64_u64_7(usize, usize, usize, usize, usize, usize, usize, Struct_u64_u64, usize) void; | 444 | extern fn c_struct_u64_u64_7(usize, usize, usize, usize, usize, usize, usize, Struct_u64_u64, usize) void; |
| 445 | extern fn c_struct_u64_u64_8(usize, usize, usize, usize, usize, usize, usize, usize, Struct_u64_u64, usize) void; | 445 | extern fn c_struct_u64_u64_8(usize, usize, usize, usize, usize, usize, usize, usize, Struct_u64_u64, usize) void; |
| 446 | 446 | ||
| 447 | test "C ABI struct u64 u64" { | 447 | test "C ABI struct u64, u64" { |
| 448 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; | 448 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 449 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; | 449 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; |
| 450 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; | 450 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| ... | @@ -518,6 +518,71 @@ test "C ABI struct f64" { | ... | @@ -518,6 +518,71 @@ test "C ABI struct f64" { |
| 518 | c_struct_f64(.{ .a = 2.5 }); | 518 | c_struct_f64(.{ .a = 2.5 }); |
| 519 | } | 519 | } |
| 520 | 520 | ||
| 521 | const Struct_f32a8 = extern struct { | ||
| 522 | a: f32 align(8), | ||
| 523 | }; | ||
| 524 | |||
| 525 | export fn zig_ret_struct_f32a8() Struct_f32a8 { | ||
| 526 | return .{ .a = 1.25 }; | ||
| 527 | } | ||
| 528 | |||
| 529 | export fn zig_struct_f32a8(s: Struct_f32a8, f: f32) void { | ||
| 530 | expect(s.a == 2.75) catch @panic("test failure"); | ||
| 531 | expect(f == 3.5) catch @panic("test failure"); | ||
| 532 | } | ||
| 533 | |||
| 534 | extern fn c_ret_struct_f32a8() Struct_f32a8; | ||
| 535 | |||
| 536 | extern fn c_struct_f32a8(Struct_f32a8, f32) void; | ||
| 537 | |||
| 538 | test "C ABI struct f32 align(8)" { | ||
| 539 | if (builtin.cpu.arch.isArm()) return error.SkipZigTest; | ||
| 540 | if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; | ||
| 541 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; | ||
| 542 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | ||
| 543 | if (builtin.cpu.arch == .riscv32) return error.SkipZigTest; | ||
| 544 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | ||
| 545 | if (builtin.cpu.arch == .x86) return error.SkipZigTest; | ||
| 546 | |||
| 547 | const s = c_ret_struct_f32a8(); | ||
| 548 | try expect(s.a == 4.125); | ||
| 549 | c_struct_f32a8(.{ .a = 5.375 }, 6.5); | ||
| 550 | } | ||
| 551 | |||
| 552 | const Struct_f32a8_f32a8 = extern struct { | ||
| 553 | a: f32 align(8), | ||
| 554 | b: f32 align(8), | ||
| 555 | }; | ||
| 556 | |||
| 557 | export fn zig_ret_struct_f32a8_f32a8() Struct_f32a8_f32a8 { | ||
| 558 | return .{ .a = 1.25, .b = 2.75 }; | ||
| 559 | } | ||
| 560 | |||
| 561 | export fn zig_struct_f32a8_f32a8(s: Struct_f32a8_f32a8, f: f32) void { | ||
| 562 | expect(s.a == 3.125) catch @panic("test failure"); | ||
| 563 | expect(s.b == 4.375) catch @panic("test failure"); | ||
| 564 | expect(f == 5.5) catch @panic("test failure"); | ||
| 565 | } | ||
| 566 | |||
| 567 | extern fn c_ret_struct_f32a8_f32a8() Struct_f32a8_f32a8; | ||
| 568 | |||
| 569 | extern fn c_struct_f32a8_f32a8(Struct_f32a8_f32a8, f32) void; | ||
| 570 | |||
| 571 | test "C ABI struct f32 align(8), f32 align(8)" { | ||
| 572 | if (builtin.cpu.arch.isArm()) return error.SkipZigTest; | ||
| 573 | if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; | ||
| 574 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; | ||
| 575 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | ||
| 576 | if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; | ||
| 577 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | ||
| 578 | if (builtin.cpu.arch == .x86) return error.SkipZigTest; | ||
| 579 | |||
| 580 | const s = c_ret_struct_f32a8_f32a8(); | ||
| 581 | try expect(s.a == 6.625); | ||
| 582 | try expect(s.b == 7.875); | ||
| 583 | c_struct_f32a8_f32a8(.{ .a = 8.0625, .b = 9.1875 }, 10.5); | ||
| 584 | } | ||
| 585 | |||
| 521 | const Struct_f32f32_f32 = extern struct { | 586 | const Struct_f32f32_f32 = extern struct { |
| 522 | a: extern struct { b: f32, c: f32 }, | 587 | a: extern struct { b: f32, c: f32 }, |
| 523 | d: f32, | 588 | d: f32, |
| ... | @@ -537,7 +602,7 @@ extern fn c_ret_struct_f32f32_f32() Struct_f32f32_f32; | ... | @@ -537,7 +602,7 @@ extern fn c_ret_struct_f32f32_f32() Struct_f32f32_f32; |
| 537 | 602 | ||
| 538 | extern fn c_struct_f32f32_f32(Struct_f32f32_f32) void; | 603 | extern fn c_struct_f32f32_f32(Struct_f32f32_f32) void; |
| 539 | 604 | ||
| 540 | test "C ABI struct {f32,f32} f32" { | 605 | test "C ABI struct {f32, f32}, f32" { |
| 541 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; | 606 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 542 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; | 607 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; |
| 543 | if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest; | 608 | if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest; |