| 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 | 1 | const assert = @import("std").debug.assert; |
| 2 | 2 | const std = @import("std"); |
| 3 | const InternPool = @import("../../InternPool.zig"); | |
| 3 | 4 | const Type = @import("../../Type.zig"); |
| 4 | 5 | const Zcu = @import("../../Zcu.zig"); |
| 5 | 6 | |
| ... | ... | @@ -15,12 +16,10 @@ pub const Class = union(enum) { |
| 15 | 16 | pub fn classifyType(ty: Type, zcu: *Zcu) Class { |
| 16 | 17 | assert(ty.hasRuntimeBits(zcu)); |
| 17 | 18 | |
| 18 | var maybe_float_bits: ?u16 = null; | |
| 19 | 19 | switch (ty.zigTypeTag(zcu)) { |
| 20 | 20 | .@"struct" => { |
| 21 | 21 | if (ty.containerLayout(zcu) == .@"packed") return .byval; |
| 22 | const float_count = countFloats(ty, zcu, &maybe_float_bits); | |
| 23 | if (float_count <= sret_float_count) return .{ .float_array = float_count }; | |
| 22 | if (countFloats(ty, zcu)) |float| return .{ .float_array = float.count }; | |
| 24 | 23 | |
| 25 | 24 | const bit_size = ty.bitSize(zcu); |
| 26 | 25 | if (bit_size > 128) return .memory; |
| ... | ... | @@ -29,8 +28,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class { |
| 29 | 28 | }, |
| 30 | 29 | .@"union" => { |
| 31 | 30 | if (ty.containerLayout(zcu) == .@"packed") return .byval; |
| 32 | const float_count = countFloats(ty, zcu, &maybe_float_bits); | |
| 33 | if (float_count <= sret_float_count) return .{ .float_array = float_count }; | |
| 31 | if (countFloats(ty, zcu)) |float| return .{ .float_array = float.count }; | |
| 34 | 32 | |
| 35 | 33 | const bit_size = ty.bitSize(zcu); |
| 36 | 34 | if (bit_size > 128) return .memory; |
| ... | ... | @@ -70,46 +68,52 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class { |
| 70 | 68 | } |
| 71 | 69 | } |
| 72 | 70 | |
| 73 | const sret_float_count = 4; | |
| 74 | fn countFloats(ty: Type, zcu: *Zcu, maybe_float_bits: *?u16) u8 { | |
| 71 | const CountFloatsResult = struct { | |
| 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 | 80 | const ip = &zcu.intern_pool; |
| 76 | const target = zcu.getTarget(); | |
| 77 | const invalid = std.math.maxInt(u8); | |
| 81 | if (!ty.hasRuntimeBits(zcu)) return .none; | |
| 78 | 82 | switch (ty.zigTypeTag(zcu)) { |
| 79 | 83 | .@"union" => { |
| 80 | const union_obj = zcu.typeToUnion(ty).?; | |
| 81 | var max_count: u8 = 0; | |
| 82 | for (union_obj.field_types.get(ip)) |field_ty| { | |
| 83 | const field_count = countFloats(Type.fromInterned(field_ty), zcu, maybe_float_bits); | |
| 84 | if (field_count == invalid) return invalid; | |
| 85 | if (field_count > max_count) max_count = field_count; | |
| 86 | if (max_count > sret_float_count) return invalid; | |
| 84 | const loaded_union = zcu.typeToUnion(ty).?; | |
| 85 | var result: CountFloatsResult = .none; | |
| 86 | for (loaded_union.field_types.get(ip)) |field_ty| { | |
| 87 | const float = countFloats(Type.fromInterned(field_ty), zcu) orelse return null; | |
| 88 | if (result.ty.toIntern() == .void_type) { | |
| 89 | result.ty = float.ty; | |
| 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 | 96 | .@"struct" => { |
| 91 | const fields_len = ty.structFieldCount(zcu); | |
| 92 | var count: u8 = 0; | |
| 93 | var i: u32 = 0; | |
| 94 | while (i < fields_len) : (i += 1) { | |
| 95 | const field_ty = ty.fieldType(i, zcu); | |
| 96 | const field_count = countFloats(field_ty, zcu, maybe_float_bits); | |
| 97 | if (field_count == invalid) return invalid; | |
| 98 | count += field_count; | |
| 99 | if (count > sret_float_count) return invalid; | |
| 97 | var result: CountFloatsResult = .none; | |
| 98 | var field_it: InternPool.LoadedStructType.RuntimeOrderIterator = if (zcu.typeToStruct(ty)) |loaded_struct| | |
| 99 | loaded_struct.iterateRuntimeOrder(ip) | |
| 100 | else | |
| 101 | .{ .runtime_order = null, .fields_len = ty.structFieldCount(zcu), .next_index = 0 }; | |
| 102 | while (field_it.next()) |field_index| { | |
| 103 | if (ty.structFieldOffset(field_index, zcu) != result.ty.abiSize(zcu) * result.count) return null; | |
| 104 | const field_ty = ty.fieldType(field_index, zcu); | |
| 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 => { | |
| 104 | const float_bits = maybe_float_bits.* orelse { | |
| 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, | |
| 115 | .float => return .{ .ty = ty, .count = 1 }, | |
| 116 | else => return null, | |
| 113 | 117 | } |
| 114 | 118 | } |
| 115 | 119 | |
| ... | ... | @@ -117,17 +121,19 @@ pub fn getFloatArrayType(ty: Type, zcu: *Zcu) ?Type { |
| 117 | 121 | const ip = &zcu.intern_pool; |
| 118 | 122 | switch (ty.zigTypeTag(zcu)) { |
| 119 | 123 | .@"union" => { |
| 120 | const union_obj = zcu.typeToUnion(ty).?; | |
| 121 | for (union_obj.field_types.get(ip)) |field_ty| { | |
| 124 | const loaded_union = zcu.typeToUnion(ty).?; | |
| 125 | for (loaded_union.field_types.get(ip)) |field_ty| { | |
| 122 | 126 | if (getFloatArrayType(Type.fromInterned(field_ty), zcu)) |some| return some; |
| 123 | 127 | } |
| 124 | 128 | return null; |
| 125 | 129 | }, |
| 126 | 130 | .@"struct" => { |
| 127 | const fields_len = ty.structFieldCount(zcu); | |
| 128 | var i: u32 = 0; | |
| 129 | while (i < fields_len) : (i += 1) { | |
| 130 | const field_ty = ty.fieldType(i, zcu); | |
| 131 | var field_it: InternPool.LoadedStructType.RuntimeOrderIterator = if (zcu.typeToStruct(ty)) |loaded_struct| | |
| 132 | loaded_struct.iterateRuntimeOrder(ip) | |
| 133 | else | |
| 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 | 137 | if (getFloatArrayType(field_ty, zcu)) |some| return some; |
| 132 | 138 | } |
| 133 | 139 | return null; |
src/codegen/llvm/FuncGen.zig+7-6| ... | ... | @@ -6707,17 +6707,18 @@ const ParamTypeIterator = struct { |
| 6707 | 6707 | .double_integer => return Lowering{ .i64_array = 2 }, |
| 6708 | 6708 | .fields => { |
| 6709 | 6709 | it.types_len = 0; |
| 6710 | var offset: u64 = 0; | |
| 6711 | for (0..ty.structFieldCount(zcu)) |field_index| { | |
| 6710 | var field_it: InternPool.LoadedStructType.RuntimeOrderIterator = if (zcu.typeToStruct(ty)) |loaded_struct| | |
| 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 | 6715 | const field_ty = ty.fieldType(field_index, zcu); |
| 6713 | 6716 | if (!field_ty.hasRuntimeBits(zcu)) continue; |
| 6714 | offset = field_ty.abiAlignment(zcu).forward(offset); | |
| 6715 | 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 | 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 | 6722 | it.llvm_index += it.types_len - 1; |
| 6722 | 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 | 181632 | else => break, |
| 181633 | 181633 | }; |
| 181634 | 181634 | } else { |
| 181635 | var part_sizes: u64 = 0; | |
| 181636 | for (parts) |part| part_sizes += part.abiSize(zcu); | |
| 181637 | if (part_sizes == ty.abiSize(zcu)) return parts; | |
| 181635 | var parts_size: u64 = 0; | |
| 181636 | for (parts) |part| parts_size += part.abiSize(zcu); | |
| 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 | 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 | 300 | for (result, 0..) |class, i| switch (class) { |
| 301 | 301 | .memory => return Class.stack, |
| 302 | 302 | .x87up => if (i == 0 or result[i - 1] != .x87) return Class.stack, |
| 303 | else => continue, | |
| 303 | else => {}, | |
| 304 | 304 | }; |
| 305 | 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 | 307 | // is passed in memory." |
| 308 | 308 | if (ty_size > 16 and (result[0] != .sse or |
| 309 | 309 | std.mem.indexOfNone(Class, result[1..], &.{ .sseup, .none }) != null)) return Class.stack; |
| 310 | 310 | |
| 311 | 311 | // "If SSEUP is not preceded by SSE or SSEUP, it is converted to SSE." |
| 312 | for (&result, 0..) |*item, i| { | |
| 313 | if (item.* == .sseup) switch (result[i - 1]) { | |
| 314 | .sse, .sseup => continue, | |
| 315 | else => item.* = .sse, | |
| 316 | }; | |
| 317 | } | |
| 312 | for (&result, 0..) |*class, i| switch (class.*) { | |
| 313 | .sseup => switch (result[i - 1]) { | |
| 314 | .sse, .sseup => {}, | |
| 315 | else => class.* = .sse, | |
| 316 | }, | |
| 317 | .float => if (i + 1 < result.len) switch (result[i + 1]) { | |
| 318 | .none => {}, | |
| 319 | else => class.* = .float_combine, | |
| 320 | }, | |
| 321 | else => {}, | |
| 322 | }; | |
| 318 | 323 | return result; |
| 319 | 324 | }, |
| 320 | 325 | .array => { |
test/c_abi/cfuncs.c+93-13| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | 1 | #include <complex.h> |
| 2 | 2 | #include <inttypes.h> |
| 3 | #include <stdalign.h> | |
| 3 | 4 | #include <stdbool.h> |
| 4 | 5 | #include <stdlib.h> |
| 5 | 6 | #include <string.h> |
| ... | ... | @@ -209,7 +210,7 @@ struct Struct_u8 zig_ret_struct_u8(void); |
| 209 | 210 | void zig_struct_u8(struct Struct_u8, size_t); |
| 210 | 211 | |
| 211 | 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 | 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 | 227 | void zig_struct_u16(struct Struct_u16, size_t); |
| 227 | 228 | |
| 228 | 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 | 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 | 244 | void zig_struct_u32(struct Struct_u32, size_t); |
| 244 | 245 | |
| 245 | 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 | 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 | 261 | void zig_struct_u64(struct Struct_u64, size_t); |
| 261 | 262 | |
| 262 | 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 | 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 | 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 | 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 | 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 | 345 | void zig_struct_f32(struct Struct_f32); |
| 345 | 346 | |
| 346 | 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 | 351 | void c_struct_f32(struct Struct_f32 s) { |
| ... | ... | @@ -360,13 +361,49 @@ struct Struct_f64 zig_ret_struct_f64(void); |
| 360 | 361 | void zig_struct_f64(struct Struct_f64); |
| 361 | 362 | |
| 362 | 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 | 367 | void c_struct_f64(struct Struct_f64 s) { |
| 367 | 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 | 407 | struct Struct_f32f32_f32 { |
| 371 | 408 | struct { |
| 372 | 409 | float b, c; |
| ... | ... | @@ -379,7 +416,7 @@ struct Struct_f32f32_f32 zig_ret_struct_f32f32_f32(void); |
| 379 | 416 | void zig_struct_f32f32_f32(struct Struct_f32f32_f32); |
| 380 | 417 | |
| 381 | 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 | 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 | 437 | void zig_struct_f32_f32f32(struct Struct_f32_f32f32); |
| 401 | 438 | |
| 402 | 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 | 443 | void c_struct_f32_f32f32(struct Struct_f32_f32f32 s) { |
| ... | ... | @@ -2870,7 +2907,7 @@ void run_c_tests(void) { |
| 2870 | 2907 | { |
| 2871 | 2908 | struct Struct_f32 s = zig_ret_struct_f32(); |
| 2872 | 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 | 2912 | #endif |
| 2876 | 2913 | |
| ... | ... | @@ -2879,17 +2916,60 @@ void run_c_tests(void) { |
| 2879 | 2916 | { |
| 2880 | 2917 | struct Struct_f64 s = zig_ret_struct_f64(); |
| 2881 | 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 | 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 | 2966 | #if !defined(__loongarch__) && !defined(__mips64__) |
| 2887 | 2967 | { |
| 2888 | 2968 | struct Struct_f32f32_f32 s = zig_ret_struct_f32f32_f32(); |
| 2889 | 2969 | assert_or_panic(s.a.b == 1.0f); |
| 2890 | 2970 | assert_or_panic(s.a.c == 2.0f); |
| 2891 | 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 | 2977 | assert_or_panic(s.a == 1.0f); |
| 2898 | 2978 | assert_or_panic(s.b.c == 2.0f); |
| 2899 | 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 | 2982 | #endif |
| 2903 | 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 | 444 | extern fn c_struct_u64_u64_7(usize, usize, usize, usize, usize, usize, usize, Struct_u64_u64, usize) void; |
| 445 | 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 | 448 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 449 | 449 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; |
| 450 | 450 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| ... | ... | @@ -518,6 +518,71 @@ test "C ABI struct f64" { |
| 518 | 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 | 586 | const Struct_f32f32_f32 = extern struct { |
| 522 | 587 | a: extern struct { b: f32, c: f32 }, |
| 523 | 588 | d: f32, |
| ... | ... | @@ -537,7 +602,7 @@ extern fn c_ret_struct_f32f32_f32() Struct_f32f32_f32; |
| 537 | 602 | |
| 538 | 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 | 606 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 542 | 607 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; |
| 543 | 608 | if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest; |