| ... | ... | @@ -3,7 +3,6 @@ const builtin = @import("builtin"); |
| 3 | 3 | const assert = std.debug.assert; |
| 4 | 4 | const expect = std.testing.expect; |
| 5 | 5 | const expectEqual = std.testing.expectEqual; |
| 6 | | const native_endian = builtin.cpu.arch.endian(); |
| 7 | 6 | |
| 8 | 7 | test "flags in packed structs" { |
| 9 | 8 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -163,26 +162,24 @@ test "correct sizeOf and offsets in packed structs" { |
| 163 | 162 | try expectEqual(22, @bitOffsetOf(PStruct, "u10_b")); |
| 164 | 163 | try expectEqual(4, @sizeOf(PStruct)); |
| 165 | 164 | |
| 166 | | if (native_endian == .little) { |
| 167 | | const s1 = @as(PStruct, @bitCast(@as(u32, 0x12345678))); |
| 168 | | try expectEqual(false, s1.bool_a); |
| 169 | | try expectEqual(false, s1.bool_b); |
| 170 | | try expectEqual(false, s1.bool_c); |
| 171 | | try expectEqual(true, s1.bool_d); |
| 172 | | try expectEqual(true, s1.bool_e); |
| 173 | | try expectEqual(true, s1.bool_f); |
| 174 | | try expectEqual(1, s1.u1_a); |
| 175 | | try expectEqual(false, s1.bool_g); |
| 176 | | try expectEqual(0, s1.u1_b); |
| 177 | | try expectEqual(3, s1.u3_a); |
| 178 | | try expectEqual(0b1101000101, s1.u10_a); |
| 179 | | try expectEqual(0b0001001000, s1.u10_b); |
| 180 | | |
| 181 | | const s2 = @as(packed struct { x: u1, y: u7, z: u24 }, @bitCast(@as(u32, 0xd5c71ff4))); |
| 182 | | try expectEqual(0, s2.x); |
| 183 | | try expectEqual(0b1111010, s2.y); |
| 184 | | try expectEqual(0xd5c71f, s2.z); |
| 185 | | } |
| 165 | const s1 = @as(PStruct, @bitCast(@as(u32, 0x12345678))); |
| 166 | try expectEqual(false, s1.bool_a); |
| 167 | try expectEqual(false, s1.bool_b); |
| 168 | try expectEqual(false, s1.bool_c); |
| 169 | try expectEqual(true, s1.bool_d); |
| 170 | try expectEqual(true, s1.bool_e); |
| 171 | try expectEqual(true, s1.bool_f); |
| 172 | try expectEqual(1, s1.u1_a); |
| 173 | try expectEqual(false, s1.bool_g); |
| 174 | try expectEqual(0, s1.u1_b); |
| 175 | try expectEqual(3, s1.u3_a); |
| 176 | try expectEqual(0b1101000101, s1.u10_a); |
| 177 | try expectEqual(0b0001001000, s1.u10_b); |
| 178 | |
| 179 | const s2 = @as(packed struct { x: u1, y: u7, z: u24 }, @bitCast(@as(u32, 0xd5c71ff4))); |
| 180 | try expectEqual(0, s2.x); |
| 181 | try expectEqual(0b1111010, s2.y); |
| 182 | try expectEqual(0xd5c71f, s2.z); |
| 186 | 183 | } |
| 187 | 184 | |
| 188 | 185 | test "nested packed structs" { |
| ... | ... | @@ -202,15 +199,13 @@ test "nested packed structs" { |
| 202 | 199 | try expectEqual(3, @offsetOf(S3, "y")); |
| 203 | 200 | try expectEqual(24, @bitOffsetOf(S3, "y")); |
| 204 | 201 | |
| 205 | | if (native_endian == .little) { |
| 206 | | const s3 = @as(S3Padded, @bitCast(@as(u64, 0xe952d5c71ff4))).s3; |
| 207 | | try expectEqual(0xf4, s3.x.a); |
| 208 | | try expectEqual(0x1f, s3.x.b); |
| 209 | | try expectEqual(0xc7, s3.x.c); |
| 210 | | try expectEqual(0xd5, s3.y.d); |
| 211 | | try expectEqual(0x52, s3.y.e); |
| 212 | | try expectEqual(0xe9, s3.y.f); |
| 213 | | } |
| 202 | const s3 = @as(S3Padded, @bitCast(@as(u64, 0xe952d5c71ff4))).s3; |
| 203 | try expectEqual(0xf4, s3.x.a); |
| 204 | try expectEqual(0x1f, s3.x.b); |
| 205 | try expectEqual(0xc7, s3.x.c); |
| 206 | try expectEqual(0xd5, s3.y.d); |
| 207 | try expectEqual(0x52, s3.y.e); |
| 208 | try expectEqual(0xe9, s3.y.f); |
| 214 | 209 | |
| 215 | 210 | const S4 = packed struct { a: i32, b: i8 }; |
| 216 | 211 | const S5 = packed struct { a: i32, b: i8, c: S4 }; |
| ... | ... | @@ -252,7 +247,6 @@ test "nested packed struct unaligned" { |
| 252 | 247 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 253 | 248 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 254 | 249 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 255 | | if (native_endian != .little) return error.SkipZigTest; // Byte aligned packed struct field pointers have not been implemented yet |
| 256 | 250 | |
| 257 | 251 | const S1 = packed struct { |
| 258 | 252 | a: u4, |
| ... | ... | @@ -344,21 +338,12 @@ test "byte-aligned field pointer offsets" { |
| 344 | 338 | .c = 3, |
| 345 | 339 | .d = 4, |
| 346 | 340 | }; |
| 347 | | switch (comptime builtin.cpu.arch.endian()) { |
| 348 | | .little => { |
| 349 | | comptime assert(@TypeOf(&a.a) == *align(4) u8); |
| 350 | | comptime assert(@TypeOf(&a.b) == *u8); |
| 351 | | comptime assert(@TypeOf(&a.c) == *align(2) u8); |
| 352 | | comptime assert(@TypeOf(&a.d) == *u8); |
| 353 | | }, |
| 354 | | .big => { |
| 355 | | // TODO re-evaluate packed struct endianness |
| 356 | | comptime assert(@TypeOf(&a.a) == *align(4:0:4) u8); |
| 357 | | comptime assert(@TypeOf(&a.b) == *align(4:8:4) u8); |
| 358 | | comptime assert(@TypeOf(&a.c) == *align(4:16:4) u8); |
| 359 | | comptime assert(@TypeOf(&a.d) == *align(4:24:4) u8); |
| 360 | | }, |
| 361 | | } |
| 341 | |
| 342 | comptime assert(@TypeOf(&a.a) == *align(4:0:4) u8); |
| 343 | comptime assert(@TypeOf(&a.b) == *align(4:8:4) u8); |
| 344 | comptime assert(@TypeOf(&a.c) == *align(4:16:4) u8); |
| 345 | comptime assert(@TypeOf(&a.d) == *align(4:24:4) u8); |
| 346 | |
| 362 | 347 | try expect(a.a == 1); |
| 363 | 348 | try expect(a.b == 2); |
| 364 | 349 | try expect(a.c == 3); |
| ... | ... | @@ -392,16 +377,10 @@ test "byte-aligned field pointer offsets" { |
| 392 | 377 | .a = 1, |
| 393 | 378 | .b = 2, |
| 394 | 379 | }; |
| 395 | | switch (comptime builtin.cpu.arch.endian()) { |
| 396 | | .little => { |
| 397 | | comptime assert(@TypeOf(&b.a) == *align(4) u16); |
| 398 | | comptime assert(@TypeOf(&b.b) == *u16); |
| 399 | | }, |
| 400 | | .big => { |
| 401 | | comptime assert(@TypeOf(&b.a) == *align(4:0:4) u16); |
| 402 | | comptime assert(@TypeOf(&b.b) == *align(4:16:4) u16); |
| 403 | | }, |
| 404 | | } |
| 380 | |
| 381 | comptime assert(@TypeOf(&b.a) == *align(4:0:4) u16); |
| 382 | comptime assert(@TypeOf(&b.b) == *align(4:16:4) u16); |
| 383 | |
| 405 | 384 | try expect(b.a == 1); |
| 406 | 385 | try expect(b.b == 2); |
| 407 | 386 | |
| ... | ... | @@ -426,7 +405,6 @@ test "nested packed struct field pointers" { |
| 426 | 405 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 427 | 406 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // ubsan unaligned pointer access |
| 428 | 407 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO |
| 429 | | if (native_endian != .little) return error.SkipZigTest; // Byte aligned packed struct field pointers have not been implemented yet |
| 430 | 408 | |
| 431 | 409 | const S2 = packed struct { |
| 432 | 410 | base: u8, |
| ... | ... | @@ -483,7 +461,6 @@ test "@intFromPtr on a packed struct field" { |
| 483 | 461 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 484 | 462 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 485 | 463 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 486 | | if (native_endian != .little) return error.SkipZigTest; |
| 487 | 464 | |
| 488 | 465 | const S = struct { |
| 489 | 466 | const P = packed struct { |
| ... | ... | @@ -498,14 +475,13 @@ test "@intFromPtr on a packed struct field" { |
| 498 | 475 | .z = 0, |
| 499 | 476 | }; |
| 500 | 477 | }; |
| 501 | | try expect(@intFromPtr(&S.p0.z) - @intFromPtr(&S.p0.x) == 2); |
| 478 | try expect(@intFromPtr(&S.p0.z) - @intFromPtr(&S.p0.x) == 0); |
| 502 | 479 | } |
| 503 | 480 | |
| 504 | 481 | test "@intFromPtr on a packed struct field unaligned and nested" { |
| 505 | 482 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 506 | 483 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 507 | 484 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 508 | | if (native_endian != .little) return error.SkipZigTest; // Byte aligned packed struct field pointers have not been implemented yet |
| 509 | 485 | |
| 510 | 486 | const S1 = packed struct { |
| 511 | 487 | a: u4, |
| ... | ... | @@ -565,16 +541,16 @@ test "@intFromPtr on a packed struct field unaligned and nested" { |
| 565 | 541 | else => {}, |
| 566 | 542 | } |
| 567 | 543 | try expect(@intFromPtr(&S2.s.base) - @intFromPtr(&S2.s) == 0); |
| 568 | | try expect(@intFromPtr(&S2.s.p0.a) - @intFromPtr(&S2.s) == 1); |
| 569 | | try expect(@intFromPtr(&S2.s.p0.b) - @intFromPtr(&S2.s) == 1); |
| 570 | | try expect(@intFromPtr(&S2.s.p0.c) - @intFromPtr(&S2.s) == 2); |
| 544 | try expect(@intFromPtr(&S2.s.p0.a) - @intFromPtr(&S2.s) == 0); |
| 545 | try expect(@intFromPtr(&S2.s.p0.b) - @intFromPtr(&S2.s) == 0); |
| 546 | try expect(@intFromPtr(&S2.s.p0.c) - @intFromPtr(&S2.s) == 0); |
| 571 | 547 | try expect(@intFromPtr(&S2.s.bit0) - @intFromPtr(&S2.s) == 0); |
| 572 | 548 | try expect(@intFromPtr(&S2.s.p1.a) - @intFromPtr(&S2.s) == 0); |
| 573 | 549 | try expect(@intFromPtr(&S2.s.p2.a) - @intFromPtr(&S2.s) == 0); |
| 574 | | try expect(@intFromPtr(&S2.s.p2.b) - @intFromPtr(&S2.s) == 5); |
| 575 | | try expect(@intFromPtr(&S2.s.p3.a) - @intFromPtr(&S2.s) == 6); |
| 576 | | try expect(@intFromPtr(&S2.s.p3.b) - @intFromPtr(&S2.s) == 6); |
| 577 | | try expect(@intFromPtr(&S2.s.p3.c) - @intFromPtr(&S2.s) == 7); |
| 550 | try expect(@intFromPtr(&S2.s.p2.b) - @intFromPtr(&S2.s) == 0); |
| 551 | try expect(@intFromPtr(&S2.s.p3.a) - @intFromPtr(&S2.s) == 0); |
| 552 | try expect(@intFromPtr(&S2.s.p3.b) - @intFromPtr(&S2.s) == 0); |
| 553 | try expect(@intFromPtr(&S2.s.p3.c) - @intFromPtr(&S2.s) == 0); |
| 578 | 554 | |
| 579 | 555 | const S3 = packed struct { |
| 580 | 556 | pad: u8, |
| ... | ... | @@ -597,7 +573,7 @@ test "@intFromPtr on a packed struct field unaligned and nested" { |
| 597 | 573 | comptime assert(@TypeOf(&S3.v0.s.v) == *align(4:10:4) u3); |
| 598 | 574 | comptime assert(@TypeOf(&S3.v0.s.s.v) == *align(4:13:4) u2); |
| 599 | 575 | comptime assert(@TypeOf(&S3.v0.s.s.s.bit0) == *align(4:15:4) u1); |
| 600 | | comptime assert(@TypeOf(&S3.v0.s.s.s.byte) == *align(2) u8); |
| 576 | comptime assert(@TypeOf(&S3.v0.s.s.s.byte) == *align(4:16:4) u8); |
| 601 | 577 | comptime assert(@TypeOf(&S3.v0.s.s.s.bit1) == *align(4:24:4) u1); |
| 602 | 578 | try expect(@intFromPtr(&S3.v0.v) - @intFromPtr(&S3.v0) == 0); |
| 603 | 579 | try expect(@intFromPtr(&S3.v0.s) - @intFromPtr(&S3.v0) == 0); |
| ... | ... | @@ -606,7 +582,7 @@ test "@intFromPtr on a packed struct field unaligned and nested" { |
| 606 | 582 | try expect(@intFromPtr(&S3.v0.s.s.v) - @intFromPtr(&S3.v0) == 0); |
| 607 | 583 | try expect(@intFromPtr(&S3.v0.s.s.s) - @intFromPtr(&S3.v0) == 0); |
| 608 | 584 | try expect(@intFromPtr(&S3.v0.s.s.s.bit0) - @intFromPtr(&S3.v0) == 0); |
| 609 | | try expect(@intFromPtr(&S3.v0.s.s.s.byte) - @intFromPtr(&S3.v0) == 2); |
| 585 | try expect(@intFromPtr(&S3.v0.s.s.s.byte) - @intFromPtr(&S3.v0) == 0); |
| 610 | 586 | try expect(@intFromPtr(&S3.v0.s.s.s.bit1) - @intFromPtr(&S3.v0) == 0); |
| 611 | 587 | } |
| 612 | 588 | |
| ... | ... | @@ -915,17 +891,8 @@ test "overaligned pointer to packed struct" { |
| 915 | 891 | const S = packed struct { a: u32, b: u32 }; |
| 916 | 892 | var foo: S align(4) = .{ .a = 123, .b = 456 }; |
| 917 | 893 | const ptr: *align(4) S = &foo; |
| 918 | | switch (comptime builtin.cpu.arch.endian()) { |
| 919 | | .little => { |
| 920 | | const ptr_to_b: *u32 = &ptr.b; |
| 921 | | try expect(ptr_to_b.* == 456); |
| 922 | | }, |
| 923 | | .big => { |
| 924 | | // Byte aligned packed struct field pointers have not been implemented yet. |
| 925 | | const ptr_to_a: *align(4:0:8) u32 = &ptr.a; |
| 926 | | try expect(ptr_to_a.* == 123); |
| 927 | | }, |
| 928 | | } |
| 894 | const ptr_to_a: *align(4:0:8) u32 = &ptr.a; |
| 895 | try expect(ptr_to_a.* == 123); |
| 929 | 896 | } |
| 930 | 897 | |
| 931 | 898 | test "packed struct initialized in bitcast" { |