master
   1const std = @import("std");
   2const builtin = @import("builtin");
   3const assert = std.debug.assert;
   4const expect = std.testing.expect;
   5const expectEqual = std.testing.expectEqual;
   6
   7test "flags in packed structs" {
   8    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
   9
  10    const Flags1 = packed struct {
  11        // first 8 bits
  12        b0_0: u1,
  13        b0_1: u1,
  14        b0_2: u1,
  15        b0_3: u1,
  16        b0_4: u1,
  17        b0_5: u1,
  18        b0_6: u1,
  19        b0_7: u1,
  20
  21        // 7 more bits
  22        b1_0: u1,
  23        b1_1: u1,
  24        b1_2: u1,
  25        b1_3: u1,
  26        b1_4: u1,
  27        b1_5: u1,
  28        b1_6: u1,
  29
  30        // some padding to fill to 24 bits
  31        _: u9,
  32    };
  33
  34    try expectEqual(@sizeOf(u24), @sizeOf(Flags1));
  35    try expectEqual(24, @bitSizeOf(Flags1));
  36
  37    const Flags2 = packed struct {
  38        // byte 0
  39        b0_0: u1,
  40        b0_1: u1,
  41        b0_2: u1,
  42        b0_3: u1,
  43        b0_4: u1,
  44        b0_5: u1,
  45        b0_6: u1,
  46        b0_7: u1,
  47
  48        // partial byte 1 (but not 8 bits)
  49        b1_0: u1,
  50        b1_1: u1,
  51        b1_2: u1,
  52        b1_3: u1,
  53        b1_4: u1,
  54        b1_5: u1,
  55        b1_6: u1,
  56
  57        // some padding that should yield @sizeOf(Flags2) == 4
  58        _: u10,
  59    };
  60
  61    try expectEqual(@sizeOf(u25), @sizeOf(Flags2));
  62    try expectEqual(25, @bitSizeOf(Flags2));
  63
  64    const Flags3 = packed struct {
  65        // byte 0
  66        b0_0: u1,
  67        b0_1: u1,
  68        b0_2: u1,
  69        b0_3: u1,
  70        b0_4: u1,
  71        b0_5: u1,
  72        b0_6: u1,
  73        b0_7: u1,
  74
  75        // byte 1
  76        b1_0: u1,
  77        b1_1: u1,
  78        b1_2: u1,
  79        b1_3: u1,
  80        b1_4: u1,
  81        b1_5: u1,
  82        b1_6: u1,
  83        b1_7: u1,
  84
  85        // some padding that should yield @sizeOf(Flags2) == 4
  86        _: u16, // it works, if the padding is 8-based
  87    };
  88
  89    try expectEqual(@sizeOf(u32), @sizeOf(Flags3));
  90    try expectEqual(32, @bitSizeOf(Flags3));
  91}
  92
  93test "consistent size of packed structs" {
  94    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
  95
  96    const TxData1 = packed struct { data: u8, _23: u23, full: bool = false };
  97    const TxData2 = packed struct { data: u9, _22: u22, full: bool = false };
  98
  99    const register_size_bits = 32;
 100    const register_size_bytes = @sizeOf(u32);
 101
 102    try expectEqual(register_size_bits, @bitSizeOf(TxData1));
 103    try expectEqual(register_size_bytes, @sizeOf(TxData1));
 104
 105    try expectEqual(register_size_bits, @bitSizeOf(TxData2));
 106    try expectEqual(register_size_bytes, @sizeOf(TxData2));
 107
 108    const TxData4 = packed struct { a: u32, b: u24 };
 109    const TxData6 = packed struct { a: u24, b: u32 };
 110
 111    const expectedBitSize = 56;
 112    const expectedByteSize = @sizeOf(u56);
 113
 114    try expectEqual(expectedBitSize, @bitSizeOf(TxData4));
 115    try expectEqual(expectedByteSize, @sizeOf(TxData4));
 116
 117    try expectEqual(expectedBitSize, @bitSizeOf(TxData6));
 118    try expectEqual(expectedByteSize, @sizeOf(TxData6));
 119}
 120
 121test "correct sizeOf and offsets in packed structs" {
 122    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 123    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 124
 125    const PStruct = packed struct {
 126        bool_a: bool,
 127        bool_b: bool,
 128        bool_c: bool,
 129        bool_d: bool,
 130        bool_e: bool,
 131        bool_f: bool,
 132        u1_a: u1,
 133        bool_g: bool,
 134        u1_b: u1,
 135        u3_a: u3,
 136        u10_a: u10,
 137        u10_b: u10,
 138    };
 139    try expectEqual(0, @offsetOf(PStruct, "bool_a"));
 140    try expectEqual(0, @bitOffsetOf(PStruct, "bool_a"));
 141    try expectEqual(0, @offsetOf(PStruct, "bool_b"));
 142    try expectEqual(1, @bitOffsetOf(PStruct, "bool_b"));
 143    try expectEqual(0, @offsetOf(PStruct, "bool_c"));
 144    try expectEqual(2, @bitOffsetOf(PStruct, "bool_c"));
 145    try expectEqual(0, @offsetOf(PStruct, "bool_d"));
 146    try expectEqual(3, @bitOffsetOf(PStruct, "bool_d"));
 147    try expectEqual(0, @offsetOf(PStruct, "bool_e"));
 148    try expectEqual(4, @bitOffsetOf(PStruct, "bool_e"));
 149    try expectEqual(0, @offsetOf(PStruct, "bool_f"));
 150    try expectEqual(5, @bitOffsetOf(PStruct, "bool_f"));
 151    try expectEqual(0, @offsetOf(PStruct, "u1_a"));
 152    try expectEqual(6, @bitOffsetOf(PStruct, "u1_a"));
 153    try expectEqual(0, @offsetOf(PStruct, "bool_g"));
 154    try expectEqual(7, @bitOffsetOf(PStruct, "bool_g"));
 155    try expectEqual(1, @offsetOf(PStruct, "u1_b"));
 156    try expectEqual(8, @bitOffsetOf(PStruct, "u1_b"));
 157    try expectEqual(1, @offsetOf(PStruct, "u3_a"));
 158    try expectEqual(9, @bitOffsetOf(PStruct, "u3_a"));
 159    try expectEqual(1, @offsetOf(PStruct, "u10_a"));
 160    try expectEqual(12, @bitOffsetOf(PStruct, "u10_a"));
 161    try expectEqual(2, @offsetOf(PStruct, "u10_b"));
 162    try expectEqual(22, @bitOffsetOf(PStruct, "u10_b"));
 163    try expectEqual(4, @sizeOf(PStruct));
 164
 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);
 183}
 184
 185test "nested packed structs" {
 186    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 187    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 188
 189    const S1 = packed struct { a: u8, b: u8, c: u8 };
 190
 191    const S2 = packed struct { d: u8, e: u8, f: u8 };
 192
 193    const S3 = packed struct { x: S1, y: S2 };
 194    const S3Padded = packed struct { s3: S3, pad: u16 };
 195
 196    try expectEqual(48, @bitSizeOf(S3));
 197    try expectEqual(@sizeOf(u48), @sizeOf(S3));
 198
 199    try expectEqual(3, @offsetOf(S3, "y"));
 200    try expectEqual(24, @bitOffsetOf(S3, "y"));
 201
 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);
 209
 210    const S4 = packed struct { a: i32, b: i8 };
 211    const S5 = packed struct { a: i32, b: i8, c: S4 };
 212    const S6 = packed struct { a: i32, b: S4, c: i8 };
 213
 214    const expectedBitSize = 80;
 215    const expectedByteSize = @sizeOf(u80);
 216    try expectEqual(expectedBitSize, @bitSizeOf(S5));
 217    try expectEqual(expectedByteSize, @sizeOf(S5));
 218    try expectEqual(expectedBitSize, @bitSizeOf(S6));
 219    try expectEqual(expectedByteSize, @sizeOf(S6));
 220
 221    try expectEqual(5, @offsetOf(S5, "c"));
 222    try expectEqual(40, @bitOffsetOf(S5, "c"));
 223    try expectEqual(9, @offsetOf(S6, "c"));
 224    try expectEqual(72, @bitOffsetOf(S6, "c"));
 225}
 226
 227test "regular in irregular packed struct" {
 228    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 229    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 230    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 231    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 232
 233    const Irregular = packed struct {
 234        bar: Regular = Regular{},
 235        _: u24 = 0,
 236        pub const Regular = packed struct { a: u16 = 0, b: u8 = 0 };
 237    };
 238
 239    var foo = Irregular{};
 240    foo.bar.a = 235;
 241    foo.bar.b = 42;
 242
 243    try expectEqual(235, foo.bar.a);
 244    try expectEqual(42, foo.bar.b);
 245}
 246
 247test "nested packed struct unaligned" {
 248    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 249    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 250    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 251
 252    const S1 = packed struct {
 253        a: u4,
 254        b: u4,
 255        c: u8,
 256    };
 257    const S2 = packed struct {
 258        base: u8,
 259        p0: S1,
 260        bit0: u1,
 261        p1: packed struct {
 262            a: u8,
 263        },
 264        p2: packed struct {
 265            a: u7,
 266            b: u8,
 267        },
 268        p3: S1,
 269
 270        var s: @This() = .{
 271            .base = 1,
 272            .p0 = .{ .a = 2, .b = 3, .c = 4 },
 273            .bit0 = 0,
 274            .p1 = .{ .a = 5 },
 275            .p2 = .{ .a = 6, .b = 7 },
 276            .p3 = .{ .a = 8, .b = 9, .c = 10 },
 277        };
 278    };
 279
 280    try expect(S2.s.base == 1);
 281    try expect(S2.s.p0.a == 2);
 282    try expect(S2.s.p0.b == 3);
 283    try expect(S2.s.p0.c == 4);
 284    try expect(S2.s.bit0 == 0);
 285    try expect(S2.s.p1.a == 5);
 286    try expect(S2.s.p2.a == 6);
 287    try expect(S2.s.p2.b == 7);
 288    try expect(S2.s.p3.a == 8);
 289    try expect(S2.s.p3.b == 9);
 290    try expect(S2.s.p3.c == 10);
 291
 292    const S3 = packed struct {
 293        pad: u8,
 294        v: u2,
 295        s: packed struct {
 296            v: u3,
 297            s: packed struct {
 298                v: u2,
 299                s: packed struct {
 300                    bit0: u1,
 301                    byte: u8,
 302                    bit1: u1,
 303                },
 304            },
 305        },
 306        var v0: @This() = .{ .pad = 0, .v = 1, .s = .{ .v = 2, .s = .{ .v = 3, .s = .{ .bit0 = 0, .byte = 4, .bit1 = 1 } } } };
 307    };
 308
 309    try expect(S3.v0.v == 1);
 310    try expect(S3.v0.s.v == 2);
 311    try expect(S3.v0.s.s.v == 3);
 312    try expect(S3.v0.s.s.s.bit0 == 0);
 313    try expect(S3.v0.s.s.s.byte == 4);
 314    try expect(S3.v0.s.s.s.bit1 == 1);
 315}
 316
 317test "byte-aligned field pointer offsets" {
 318    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 319    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 320    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 321    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 322
 323    const S = struct {
 324        const A = packed struct {
 325            a: u8,
 326            b: u8,
 327            c: u8,
 328            d: u8,
 329        };
 330
 331        const B = packed struct {
 332            a: u16,
 333            b: u16,
 334        };
 335
 336        fn doTheTest() !void {
 337            var a: A = .{
 338                .a = 1,
 339                .b = 2,
 340                .c = 3,
 341                .d = 4,
 342            };
 343
 344            comptime assert(@TypeOf(&a.a) == *align(4:0:4) u8);
 345            comptime assert(@TypeOf(&a.b) == *align(4:8:4) u8);
 346            comptime assert(@TypeOf(&a.c) == *align(4:16:4) u8);
 347            comptime assert(@TypeOf(&a.d) == *align(4:24:4) u8);
 348
 349            try expect(a.a == 1);
 350            try expect(a.b == 2);
 351            try expect(a.c == 3);
 352            try expect(a.d == 4);
 353
 354            a.a += 1;
 355            try expect(a.a == 2);
 356            try expect(a.b == 2);
 357            try expect(a.c == 3);
 358            try expect(a.d == 4);
 359
 360            a.b += 1;
 361            try expect(a.a == 2);
 362            try expect(a.b == 3);
 363            try expect(a.c == 3);
 364            try expect(a.d == 4);
 365
 366            a.c += 1;
 367            try expect(a.a == 2);
 368            try expect(a.b == 3);
 369            try expect(a.c == 4);
 370            try expect(a.d == 4);
 371
 372            a.d += 1;
 373            try expect(a.a == 2);
 374            try expect(a.b == 3);
 375            try expect(a.c == 4);
 376            try expect(a.d == 5);
 377
 378            var b: B = .{
 379                .a = 1,
 380                .b = 2,
 381            };
 382
 383            comptime assert(@TypeOf(&b.a) == *align(4:0:4) u16);
 384            comptime assert(@TypeOf(&b.b) == *align(4:16:4) u16);
 385
 386            try expect(b.a == 1);
 387            try expect(b.b == 2);
 388
 389            b.a += 1;
 390            try expect(b.a == 2);
 391            try expect(b.b == 2);
 392
 393            b.b += 1;
 394            try expect(b.a == 2);
 395            try expect(b.b == 3);
 396        }
 397    };
 398
 399    try S.doTheTest();
 400    try comptime S.doTheTest();
 401}
 402
 403test "nested packed struct field pointers" {
 404    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 405    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 406    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 407    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 408    if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // ubsan unaligned pointer access
 409    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
 410
 411    const S2 = packed struct {
 412        base: u8,
 413        p0: packed struct {
 414            a: u4,
 415            b: u4,
 416            c: u8,
 417        },
 418        bit: u1,
 419        p1: packed struct {
 420            a: u7,
 421            b: u8,
 422        },
 423
 424        var s: @This() = .{ .base = 1, .p0 = .{ .a = 2, .b = 3, .c = 4 }, .bit = 0, .p1 = .{ .a = 5, .b = 6 } };
 425    };
 426
 427    const ptr_base = &S2.s.base;
 428    const ptr_p0_a = &S2.s.p0.a;
 429    const ptr_p0_b = &S2.s.p0.b;
 430    const ptr_p0_c = &S2.s.p0.c;
 431    const ptr_p1_a = &S2.s.p1.a;
 432    const ptr_p1_b = &S2.s.p1.b;
 433    try expectEqual(1, ptr_base.*);
 434    try expectEqual(2, ptr_p0_a.*);
 435    try expectEqual(3, ptr_p0_b.*);
 436    try expectEqual(4, ptr_p0_c.*);
 437    try expectEqual(5, ptr_p1_a.*);
 438    try expectEqual(6, ptr_p1_b.*);
 439}
 440
 441test "load pointer from packed struct" {
 442    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 443    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 444    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 445    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 446    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 447
 448    const A = struct {
 449        index: u16,
 450    };
 451    const B = packed struct {
 452        x: *A,
 453        y: u32,
 454    };
 455    var a: A = .{ .index = 123 };
 456    const b_list: []const B = &.{.{ .x = &a, .y = 99 }};
 457    for (b_list) |b| {
 458        try expect(b.x.index == 123);
 459    }
 460}
 461
 462test "@intFromPtr on a packed struct field" {
 463    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 464    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 465    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 466
 467    const S = struct {
 468        const P = packed struct {
 469            x: u8,
 470            y: u8,
 471            z: u32,
 472        };
 473
 474        var p0: P = P{
 475            .x = 1,
 476            .y = 2,
 477            .z = 0,
 478        };
 479    };
 480    try expect(@intFromPtr(&S.p0.z) - @intFromPtr(&S.p0.x) == 0);
 481}
 482
 483test "@intFromPtr on a packed struct field unaligned and nested" {
 484    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 485    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 486    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 487
 488    const S1 = packed struct {
 489        a: u4,
 490        b: u4,
 491        c: u8,
 492    };
 493    const S2 = packed struct {
 494        base: u8,
 495        p0: S1,
 496        bit0: u1,
 497        p1: packed struct {
 498            a: u8,
 499        },
 500        p2: packed struct {
 501            a: u7,
 502            b: u8,
 503        },
 504        p3: S1,
 505
 506        var s: @This() = .{
 507            .base = 1,
 508            .p0 = .{ .a = 2, .b = 3, .c = 4 },
 509            .bit0 = 0,
 510            .p1 = .{ .a = 5 },
 511            .p2 = .{ .a = 6, .b = 7 },
 512            .p3 = .{ .a = 8, .b = 9, .c = 10 },
 513        };
 514    };
 515
 516    switch (comptime @alignOf(S2)) {
 517        4 => {
 518            comptime assert(@TypeOf(&S2.s.base) == *align(4) u8);
 519            comptime assert(@TypeOf(&S2.s.p0.a) == *align(1:0:2) u4);
 520            comptime assert(@TypeOf(&S2.s.p0.b) == *align(1:4:2) u4);
 521            comptime assert(@TypeOf(&S2.s.p0.c) == *u8);
 522            comptime assert(@TypeOf(&S2.s.bit0) == *align(4:24:8) u1);
 523            comptime assert(@TypeOf(&S2.s.p1.a) == *align(4:25:8) u8);
 524            comptime assert(@TypeOf(&S2.s.p2.a) == *align(4:33:8) u7);
 525            comptime assert(@TypeOf(&S2.s.p2.b) == *u8);
 526            comptime assert(@TypeOf(&S2.s.p3.a) == *align(2:0:2) u4);
 527            comptime assert(@TypeOf(&S2.s.p3.b) == *align(2:4:2) u4);
 528            comptime assert(@TypeOf(&S2.s.p3.c) == *u8);
 529        },
 530        8 => {
 531            comptime assert(@TypeOf(&S2.s.base) == *align(8) u8);
 532            comptime assert(@TypeOf(&S2.s.p0.a) == *align(1:0:2) u4);
 533            comptime assert(@TypeOf(&S2.s.p0.b) == *align(1:4:2) u4);
 534            comptime assert(@TypeOf(&S2.s.p0.c) == *u8);
 535            comptime assert(@TypeOf(&S2.s.bit0) == *align(8:24:8) u1);
 536            comptime assert(@TypeOf(&S2.s.p1.a) == *align(8:25:8) u8);
 537            comptime assert(@TypeOf(&S2.s.p2.a) == *align(8:33:8) u7);
 538            comptime assert(@TypeOf(&S2.s.p2.b) == *u8);
 539            comptime assert(@TypeOf(&S2.s.p3.a) == *align(2:0:2) u4);
 540            comptime assert(@TypeOf(&S2.s.p3.b) == *align(2:4:2) u4);
 541            comptime assert(@TypeOf(&S2.s.p3.c) == *u8);
 542        },
 543        else => {},
 544    }
 545    try expect(@intFromPtr(&S2.s.base) - @intFromPtr(&S2.s) == 0);
 546    try expect(@intFromPtr(&S2.s.p0.a) - @intFromPtr(&S2.s) == 0);
 547    try expect(@intFromPtr(&S2.s.p0.b) - @intFromPtr(&S2.s) == 0);
 548    try expect(@intFromPtr(&S2.s.p0.c) - @intFromPtr(&S2.s) == 0);
 549    try expect(@intFromPtr(&S2.s.bit0) - @intFromPtr(&S2.s) == 0);
 550    try expect(@intFromPtr(&S2.s.p1.a) - @intFromPtr(&S2.s) == 0);
 551    try expect(@intFromPtr(&S2.s.p2.a) - @intFromPtr(&S2.s) == 0);
 552    try expect(@intFromPtr(&S2.s.p2.b) - @intFromPtr(&S2.s) == 0);
 553    try expect(@intFromPtr(&S2.s.p3.a) - @intFromPtr(&S2.s) == 0);
 554    try expect(@intFromPtr(&S2.s.p3.b) - @intFromPtr(&S2.s) == 0);
 555    try expect(@intFromPtr(&S2.s.p3.c) - @intFromPtr(&S2.s) == 0);
 556
 557    const S3 = packed struct {
 558        pad: u8,
 559        v: u2,
 560        s: packed struct {
 561            v: u3,
 562            s: packed struct {
 563                v: u2,
 564                s: packed struct {
 565                    bit0: u1,
 566                    byte: u8,
 567                    bit1: u1,
 568                },
 569            },
 570        },
 571        var v0: @This() = .{ .pad = 0, .v = 1, .s = .{ .v = 2, .s = .{ .v = 3, .s = .{ .bit0 = 0, .byte = 4, .bit1 = 1 } } } };
 572    };
 573
 574    comptime assert(@TypeOf(&S3.v0.v) == *align(4:8:4) u2);
 575    comptime assert(@TypeOf(&S3.v0.s.v) == *align(4:10:4) u3);
 576    comptime assert(@TypeOf(&S3.v0.s.s.v) == *align(4:13:4) u2);
 577    comptime assert(@TypeOf(&S3.v0.s.s.s.bit0) == *align(4:15:4) u1);
 578    comptime assert(@TypeOf(&S3.v0.s.s.s.byte) == *align(4:16:4) u8);
 579    comptime assert(@TypeOf(&S3.v0.s.s.s.bit1) == *align(4:24:4) u1);
 580    try expect(@intFromPtr(&S3.v0.v) - @intFromPtr(&S3.v0) == 0);
 581    try expect(@intFromPtr(&S3.v0.s) - @intFromPtr(&S3.v0) == 0);
 582    try expect(@intFromPtr(&S3.v0.s.v) - @intFromPtr(&S3.v0) == 0);
 583    try expect(@intFromPtr(&S3.v0.s.s) - @intFromPtr(&S3.v0) == 0);
 584    try expect(@intFromPtr(&S3.v0.s.s.v) - @intFromPtr(&S3.v0) == 0);
 585    try expect(@intFromPtr(&S3.v0.s.s.s) - @intFromPtr(&S3.v0) == 0);
 586    try expect(@intFromPtr(&S3.v0.s.s.s.bit0) - @intFromPtr(&S3.v0) == 0);
 587    try expect(@intFromPtr(&S3.v0.s.s.s.byte) - @intFromPtr(&S3.v0) == 0);
 588    try expect(@intFromPtr(&S3.v0.s.s.s.bit1) - @intFromPtr(&S3.v0) == 0);
 589}
 590
 591test "packed struct fields modification" {
 592    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 593    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 594
 595    // Originally reported at https://github.com/ziglang/zig/issues/16615
 596    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 597
 598    const Small = packed struct {
 599        val: u8 = 0,
 600        lo: u4 = 0,
 601        hi: u4 = 0,
 602
 603        var p: @This() = undefined;
 604    };
 605    Small.p = .{
 606        .val = 0x12,
 607        .lo = 3,
 608        .hi = 4,
 609    };
 610    try expect(@as(u16, @bitCast(Small.p)) == 0x4312);
 611
 612    Small.p.val -= Small.p.lo;
 613    Small.p.val += Small.p.hi;
 614    Small.p.hi -= Small.p.lo;
 615    try expect(@as(u16, @bitCast(Small.p)) == 0x1313);
 616}
 617
 618test "optional pointer in packed struct" {
 619    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 620    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 621    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 622    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 623    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 624
 625    const T = packed struct { ptr: ?*const u8 };
 626    var n: u8 = 0;
 627    const x = T{ .ptr = &n };
 628    try expect(x.ptr.? == &n);
 629}
 630
 631test "nested packed struct field access test" {
 632    if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
 633    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO packed structs larger than 64 bits
 634    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 635    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 636    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 637    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 638    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 639
 640    const Vec2 = packed struct {
 641        x: f32,
 642        y: f32,
 643    };
 644
 645    const Vec3 = packed struct {
 646        x: f32,
 647        y: f32,
 648        z: f32,
 649    };
 650
 651    const NestedVec2 = packed struct {
 652        nested: Vec2,
 653    };
 654
 655    const NestedVec3 = packed struct {
 656        nested: Vec3,
 657    };
 658
 659    const vec2 = Vec2{
 660        .x = 1.0,
 661        .y = 2.0,
 662    };
 663
 664    try std.testing.expectEqual(vec2.x, 1.0);
 665    try std.testing.expectEqual(vec2.y, 2.0);
 666
 667    var vec2_o: Vec2 = undefined;
 668    const vec2_o_ptr: *Vec2 = &vec2_o;
 669    vec2_o_ptr.* = vec2;
 670
 671    try std.testing.expectEqual(vec2_o.x, 1.0);
 672    try std.testing.expectEqual(vec2_o.y, 2.0);
 673
 674    const nested_vec2 = NestedVec2{
 675        .nested = Vec2{
 676            .x = 1.0,
 677            .y = 2.0,
 678        },
 679    };
 680
 681    try std.testing.expectEqual(nested_vec2.nested.x, 1.0);
 682    try std.testing.expectEqual(nested_vec2.nested.y, 2.0);
 683
 684    var nested_o: NestedVec2 = undefined;
 685    const nested_o_ptr: *NestedVec2 = &nested_o;
 686    nested_o_ptr.* = nested_vec2;
 687
 688    try std.testing.expectEqual(nested_o.nested.x, 1.0);
 689    try std.testing.expectEqual(nested_o.nested.y, 2.0);
 690
 691    const vec3 = Vec3{
 692        .x = 1.0,
 693        .y = 2.0,
 694        .z = 3.0,
 695    };
 696
 697    try std.testing.expectEqual(vec3.x, 1.0);
 698    try std.testing.expectEqual(vec3.y, 2.0);
 699    try std.testing.expectEqual(vec3.z, 3.0);
 700
 701    var vec3_o: Vec3 = undefined;
 702    const vec3_o_ptr: *Vec3 = &vec3_o;
 703    vec3_o_ptr.* = vec3;
 704
 705    try std.testing.expectEqual(vec3_o.x, 1.0);
 706    try std.testing.expectEqual(vec3_o.y, 2.0);
 707    try std.testing.expectEqual(vec3_o.z, 3.0);
 708
 709    const nested_vec3 = NestedVec3{
 710        .nested = Vec3{
 711            .x = 1.0,
 712            .y = 2.0,
 713            .z = 3.0,
 714        },
 715    };
 716
 717    try std.testing.expectEqual(nested_vec3.nested.x, 1.0);
 718    try std.testing.expectEqual(nested_vec3.nested.y, 2.0);
 719    try std.testing.expectEqual(nested_vec3.nested.z, 3.0);
 720
 721    var nested_vec3_o: NestedVec3 = undefined;
 722    const nested_vec3_o_ptr: *NestedVec3 = &nested_vec3_o;
 723    nested_vec3_o_ptr.* = nested_vec3;
 724
 725    try std.testing.expectEqual(nested_vec3_o.nested.x, 1.0);
 726    try std.testing.expectEqual(nested_vec3_o.nested.y, 2.0);
 727    try std.testing.expectEqual(nested_vec3_o.nested.z, 3.0);
 728
 729    const hld = packed struct {
 730        c: u64,
 731        d: u32,
 732    };
 733
 734    const mld = packed struct {
 735        h: u64,
 736        i: u64,
 737    };
 738
 739    const a = packed struct {
 740        b: hld,
 741        g: mld,
 742    };
 743
 744    var arg = a{ .b = hld{ .c = 1, .d = 2 }, .g = mld{ .h = 6, .i = 8 } };
 745    _ = &arg;
 746    try std.testing.expect(arg.b.c == 1);
 747    try std.testing.expect(arg.b.d == 2);
 748    try std.testing.expect(arg.g.h == 6);
 749    try std.testing.expect(arg.g.i == 8);
 750}
 751
 752test "nested packed struct at non-zero offset" {
 753    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 754    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 755    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 756
 757    const Pair = packed struct(u24) {
 758        a: u16 = 0,
 759        b: u8 = 0,
 760    };
 761    const A = packed struct {
 762        p1: Pair,
 763        p2: Pair,
 764    };
 765
 766    var k: u8 = 123;
 767    _ = &k;
 768    var v: A = .{
 769        .p1 = .{ .a = k + 1, .b = k },
 770        .p2 = .{ .a = k + 1, .b = k },
 771    };
 772
 773    try expect(v.p1.a == k + 1 and v.p1.b == k);
 774    try expect(v.p2.a == k + 1 and v.p2.b == k);
 775
 776    v.p2.a -= v.p1.a;
 777    v.p2.b -= v.p1.b;
 778    try expect(v.p2.a == 0 and v.p2.b == 0);
 779    try expect(v.p1.a == k + 1 and v.p1.b == k);
 780}
 781
 782test "nested packed struct at non-zero offset 2" {
 783    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 784    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 785    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 786    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 787    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO packed structs larger than 64 bits
 788    if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
 789    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 790
 791    const S = struct {
 792        const Pair = packed struct(u40) {
 793            a: u32 = 0,
 794            b: u8 = 0,
 795        };
 796        const A = packed struct {
 797            p1: Pair,
 798            p2: Pair,
 799            c: C,
 800        };
 801        const C = packed struct {
 802            p1: Pair,
 803            pad1: u5,
 804            p2: Pair,
 805            pad2: u3,
 806            last: i16,
 807        };
 808
 809        fn doTheTest() !void {
 810            var k: u8 = 123;
 811            _ = &k;
 812            var v: A = .{
 813                .p1 = .{ .a = k + 1, .b = k },
 814                .p2 = .{ .a = k + 1, .b = k },
 815                .c = .{
 816                    .pad1 = 11,
 817                    .pad2 = 2,
 818                    .p1 = .{ .a = k + 1, .b = k },
 819                    .p2 = .{ .a = k + 1, .b = k },
 820                    .last = -12345,
 821                },
 822            };
 823
 824            try expect(v.p1.a == k + 1 and v.p1.b == k);
 825            try expect(v.p2.a == k + 1 and v.p2.b == k);
 826            try expect(v.c.p2.a == k + 1 and v.c.p2.b == k);
 827            try expect(v.c.p2.a == k + 1 and v.c.p2.b == k);
 828            try expect(v.c.last == -12345);
 829            try expect(v.c.pad1 == 11 and v.c.pad2 == 2);
 830
 831            v.p2.a -= v.p1.a;
 832            v.p2.b -= v.p1.b;
 833            v.c.p2.a -= v.c.p1.a;
 834            v.c.p2.b -= v.c.p1.b;
 835            v.c.last -|= 32000;
 836            try expect(v.p2.a == 0 and v.p2.b == 0);
 837            try expect(v.p1.a == k + 1 and v.p1.b == k);
 838            try expect(v.c.p2.a == 0 and v.c.p2.b == 0);
 839            try expect(v.c.p1.a == k + 1 and v.c.p1.b == k);
 840            try expect(v.c.last == -32768);
 841            try expect(v.c.pad1 == 11 and v.c.pad2 == 2);
 842        }
 843    };
 844
 845    try S.doTheTest();
 846    try comptime S.doTheTest();
 847}
 848
 849test "runtime init of unnamed packed struct type" {
 850    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 851    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 852    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 853
 854    var z: u8 = 123;
 855    _ = &z;
 856    try (packed struct {
 857        x: u8,
 858        pub fn m(s: @This()) !void {
 859            try expect(s.x == 123);
 860        }
 861    }{ .x = z }).m();
 862}
 863
 864test "packed struct passed to callconv(.c) function" {
 865    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 866    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 867    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 868    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 869
 870    const S = struct {
 871        const Packed = packed struct {
 872            a: u16,
 873            b: bool = true,
 874            c: bool = true,
 875            d: u46 = 0,
 876        };
 877
 878        fn foo(p: Packed, a1: u64, a2: u64, a3: u64, a4: u64, a5: u64) callconv(.c) bool {
 879            return p.a == 12345 and p.b == true and p.c == true and p.d == 0 and a1 == 5 and a2 == 4 and a3 == 3 and a4 == 2 and a5 == 1;
 880        }
 881    };
 882    const result = S.foo(S.Packed{
 883        .a = 12345,
 884        .b = true,
 885        .c = true,
 886    }, 5, 4, 3, 2, 1);
 887    try expect(result);
 888}
 889
 890test "overaligned pointer to packed struct" {
 891    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 892    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 893    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 894    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 895
 896    const S = packed struct { a: u32, b: u32 };
 897    var foo: S align(4) = .{ .a = 123, .b = 456 };
 898    const ptr: *align(4) S = &foo;
 899    const ptr_to_a: *align(4:0:8) u32 = &ptr.a;
 900    try expect(ptr_to_a.* == 123);
 901}
 902
 903test "packed struct initialized in bitcast" {
 904    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 905    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 906    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 907    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 908
 909    const T = packed struct { val: u8 };
 910    var val: u8 = 123;
 911    _ = &val;
 912    const t = @as(u8, @bitCast(T{ .val = val }));
 913    try expect(t == val);
 914}
 915
 916test "pointer to container level packed struct field" {
 917    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 918    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 919    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 920    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 921    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
 922
 923    const S = packed struct(u32) {
 924        test_bit: bool,
 925        someother_data: u12,
 926        other_test_bit: bool,
 927        someother_more_different_data: u12,
 928        other_bits: packed struct(u6) {
 929            enable_1: bool,
 930            enable_2: bool,
 931            enable_3: bool,
 932            enable_4: bool,
 933            enable_5: bool,
 934            enable_6: bool,
 935        },
 936        var arr = [_]u32{0} ** 2;
 937    };
 938    @as(*S, @ptrCast(&S.arr[0])).other_bits.enable_3 = true;
 939    try expect(S.arr[0] == 0x10000000);
 940}
 941
 942test "store undefined to packed result location" {
 943    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 944    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 945    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 946
 947    var x: u4 = 0;
 948    _ = &x;
 949    const s = packed struct { x: u4, y: u4 }{ .x = x, .y = if (x > 0) x else undefined };
 950    try expectEqual(x, s.x);
 951}
 952
 953// Originally reported at https://github.com/ziglang/zig/issues/9914
 954test "bitcast back and forth" {
 955    const S = packed struct { one: u6, two: u1 };
 956    const s = S{ .one = 0b110101, .two = 0b1 };
 957    const u: u7 = @bitCast(s);
 958    const s2: S = @bitCast(u);
 959    try expect(s.one == s2.one);
 960    try expect(s.two == s2.two);
 961}
 962
 963// Originally reported at https://github.com/ziglang/zig/issues/14200
 964test "field access of packed struct smaller than its abi size inside struct initialized with rls" {
 965    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 966    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 967    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
 968
 969    const S = struct {
 970        ps: packed struct { x: i2, y: i2 },
 971
 972        fn init(cond: bool) @This() {
 973            return .{ .ps = .{ .x = 0, .y = if (cond) 1 else 0 } };
 974        }
 975    };
 976
 977    const s = S.init(true);
 978    // note: this bug is triggered by the == operator, expectEqual will hide it
 979    try expect(@as(i2, 0) == s.ps.x);
 980    try expect(@as(i2, 1) == s.ps.y);
 981}
 982
 983// Originally reported at https://github.com/ziglang/zig/issues/14632
 984test "modify nested packed struct aligned field" {
 985    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 986    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 987    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
 988    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 989
 990    const Options = packed struct {
 991        foo: bool = false,
 992        bar: bool = false,
 993        pretty_print: packed struct {
 994            enabled: bool = false,
 995            num_spaces: u4 = 4,
 996            space_char: enum(u1) { space, tab } = .space,
 997            indent: u8 = 0,
 998        } = .{},
 999        baz: bool = false,
1000    };
1001
1002    var opts = Options{};
1003    opts.pretty_print.indent += 1;
1004    try std.testing.expectEqual(0b00000000100100000, @as(u17, @bitCast(opts)));
1005    try std.testing.expect(!opts.foo);
1006    try std.testing.expect(!opts.bar);
1007    try std.testing.expect(!opts.pretty_print.enabled);
1008    try std.testing.expectEqual(4, opts.pretty_print.num_spaces);
1009    try std.testing.expectEqual(1, opts.pretty_print.indent);
1010    try std.testing.expect(!opts.baz);
1011}
1012
1013// Originally reported at https://github.com/ziglang/zig/issues/9674
1014test "assigning packed struct inside another packed struct" {
1015    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1016    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1017    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1018
1019    const S = struct {
1020        const Inner = packed struct {
1021            bits: u3,
1022            more_bits: u6,
1023        };
1024
1025        const Outer = packed struct {
1026            padding: u5,
1027            inner: Inner,
1028        };
1029        fn t(inner: Inner) void {
1030            r.inner = inner;
1031        }
1032
1033        var mem: Outer = undefined;
1034        var r: *volatile Outer = &mem;
1035    };
1036
1037    const val = S.Inner{ .bits = 1, .more_bits = 11 };
1038    S.mem.padding = 0;
1039    S.t(val);
1040
1041    try expectEqual(val, S.mem.inner);
1042    try expect(S.mem.padding == 0);
1043}
1044
1045test "packed struct acts as a namespace" {
1046    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1047
1048    const Bar = packed struct {
1049        const Baz = enum {
1050            fizz,
1051            buzz,
1052        };
1053    };
1054    var foo = Bar.Baz.fizz;
1055    _ = &foo;
1056    try expect(foo == .fizz);
1057}
1058
1059test "pointer loaded correctly from packed struct" {
1060    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1061    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1062    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1063    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
1064    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1065
1066    if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // crashes MSVC
1067
1068    const RAM = struct {
1069        data: [0xFFFF + 1]u8,
1070        fn new() !@This() {
1071            return .{ .data = [_]u8{0} ** 0x10000 };
1072        }
1073        fn get(self: *@This(), addr: u16) u8 {
1074            return self.data[addr];
1075        }
1076    };
1077
1078    const CPU = packed struct {
1079        interrupts: bool,
1080        ram: *RAM,
1081        fn new(ram: *RAM) !@This() {
1082            return .{
1083                .ram = ram,
1084                .interrupts = false,
1085            };
1086        }
1087        fn tick(self: *@This()) !void {
1088            const queued_interrupts = self.ram.get(0xFFFF) & self.ram.get(0xFF0F);
1089            if (self.interrupts and queued_interrupts != 0) {
1090                self.interrupts = false;
1091            }
1092        }
1093    };
1094
1095    var ram = try RAM.new();
1096    var cpu = try CPU.new(&ram);
1097    try cpu.tick();
1098    try std.testing.expect(cpu.interrupts == false);
1099}
1100
1101test "assignment to non-byte-aligned field in packed struct" {
1102    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1103    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1104    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1105    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
1106
1107    const Frame = packed struct {
1108        num: u20,
1109    };
1110
1111    const Entry = packed struct {
1112        other: u12,
1113        frame: Frame,
1114    };
1115
1116    const frame = Frame{ .num = 0x7FDE };
1117    var entry = Entry{ .other = 0, .frame = .{ .num = 0xFFFFF } };
1118    entry.frame = frame;
1119    try expect(entry.frame.num == 0x7FDE);
1120}
1121
1122test "packed struct field pointer aligned properly" {
1123    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1124    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1125    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
1126
1127    const Foo = packed struct {
1128        a: i32,
1129        b: u8,
1130
1131        var buffer: [256]u8 = undefined;
1132    };
1133
1134    var f1: *align(16) Foo = @alignCast(@as(*align(1) Foo, @ptrCast(&Foo.buffer[0])));
1135    try expect(@typeInfo(@TypeOf(f1)).pointer.alignment == 16);
1136    try expect(@intFromPtr(f1) == @intFromPtr(&f1.a));
1137    try expect(@typeInfo(@TypeOf(&f1.a)).pointer.alignment == 16);
1138}
1139
1140test "load flag from packed struct in union" {
1141    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1142    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1143    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1144    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1145    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1146
1147    const A = packed struct {
1148        a: bool,
1149        b: bool,
1150        c: bool,
1151        d: bool,
1152
1153        e: bool,
1154        f: bool,
1155        g: bool,
1156        h: bool,
1157    };
1158
1159    const X = union {
1160        x: A,
1161        y: u64,
1162
1163        pub fn a(_: i32, _: i32, _: i32, _: i32, _: i32, _: bool, flag_b: bool) !void {
1164            const flag_b_byte: u8 = @intFromBool(flag_b);
1165            try std.testing.expect(flag_b_byte == 1);
1166        }
1167        pub fn b(x: *@This()) !void {
1168            try a(0, 1, 2, 3, 4, x.x.a, x.x.b);
1169        }
1170    };
1171    var flags = A{
1172        .a = false,
1173        .b = true,
1174        .c = false,
1175        .d = false,
1176
1177        .e = false,
1178        .f = true,
1179        .g = false,
1180        .h = false,
1181    };
1182    _ = &flags;
1183    var x = X{
1184        .x = flags,
1185    };
1186    try X.b(&x);
1187    comptime if (@sizeOf(A) != 1) unreachable;
1188}
1189
1190test "bitcasting a packed struct at comptime and using the result" {
1191    comptime {
1192        const Struct = packed struct {
1193            x: packed union {
1194                a: u63,
1195                b: packed struct(u63) {
1196                    a: i32,
1197                    b: u31 = 0,
1198                },
1199            },
1200            y: u1,
1201
1202            pub fn bitcast(fd: u64) @This() {
1203                return @bitCast(fd);
1204            }
1205
1206            pub fn cannotReach(_: @This()) i32 {
1207                return 0;
1208            }
1209        };
1210
1211        _ = Struct.bitcast(@as(u64, 0)).cannotReach();
1212    }
1213}
1214
1215test "2-byte packed struct argument in C calling convention" {
1216    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1217    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
1218    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1219    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1220
1221    const S = packed struct(u16) {
1222        x: u15 = 0,
1223        y: u1 = 0,
1224
1225        fn foo(s: @This()) callconv(.c) i32 {
1226            return s.x;
1227        }
1228        fn bar(s: @This()) !void {
1229            try expect(foo(s) == 1);
1230        }
1231    };
1232    {
1233        var s: S = .{};
1234        s.x += 1;
1235        try S.bar(s);
1236    }
1237    comptime {
1238        var s: S = .{};
1239        s.x += 1;
1240        try S.bar(s);
1241    }
1242}
1243
1244test "packed struct contains optional pointer" {
1245    const foo: packed struct {
1246        a: ?*@This() = null,
1247    } = .{};
1248    try expect(foo.a == null);
1249}
1250
1251test "packed struct equality" {
1252    const Foo = packed struct {
1253        a: u4,
1254        b: u4,
1255    };
1256
1257    const S = struct {
1258        fn doTest(x: Foo, y: Foo) !void {
1259            try expect(x == y);
1260            try expect(!(x != y));
1261        }
1262    };
1263
1264    const x: Foo = .{ .a = 1, .b = 2 };
1265    const y: Foo = .{ .b = 2, .a = 1 };
1266
1267    try S.doTest(x, y);
1268    comptime try S.doTest(x, y);
1269}
1270
1271test "packed struct equality ignores padding bits" {
1272    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1273    if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1274    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1275
1276    const S = packed struct { b: bool };
1277    var s: S = undefined;
1278    s.b = true;
1279    try std.testing.expect(s != S{ .b = false });
1280    try std.testing.expect(s == S{ .b = true });
1281}
1282
1283test "packed struct with signed field" {
1284    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1285    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1286
1287    var s: packed struct {
1288        a: i2,
1289        b: u6,
1290    } = .{ .a = -1, .b = 42 };
1291    s = s;
1292    try expect(s.a == -1);
1293    try expect(s.b == 42);
1294}
1295
1296test "assign packed struct initialized with RLS to packed struct literal field" {
1297    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1298    if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isWasm()) return error.SkipZigTest;
1299    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1300    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1301
1302    const Inner = packed struct { x: u17 };
1303    const Outer = packed struct { inner: Inner, x: u15 };
1304
1305    var x: u15 = undefined;
1306    x = 23385;
1307    var inner: Inner = undefined;
1308    inner = .{ .x = x };
1309    const outer = Outer{ .x = x, .inner = inner };
1310    try expect(outer.inner.x == x);
1311    try expect(outer.x == x);
1312}
1313
1314test "byte-aligned packed relocation" {
1315    if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1316    if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
1317    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1318    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
1319    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1320
1321    const S = struct {
1322        var global: u8 align(2) = 0;
1323        var packed_value: packed struct { x: u8, y: *align(2) u8 } = .{ .x = 111, .y = &global };
1324    };
1325    try expect(S.packed_value.x == 111);
1326    try expect(S.packed_value.y == &S.global);
1327}
1328
1329test "packed struct store of comparison result" {
1330    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1331    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1332    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
1333
1334    const S1 = packed struct {
1335        val1: u3,
1336        val2: u3,
1337    };
1338    const S2 = packed struct {
1339        a: bool,
1340        b: bool,
1341    };
1342
1343    var A: S1 = .{ .val1 = 1, .val2 = 1 };
1344    A.val2 += 1;
1345    try expectEqual(1, A.val1);
1346    try expectEqual(2, A.val2);
1347    try expect((A.val2 & 1) != 1);
1348    const result1: S2 = .{ .a = (A.val2 & 1) != 1, .b = (A.val1 & 1) != 1 };
1349    try expect(result1.a);
1350    try expect(!result1.b);
1351
1352    try expect((A.val2 == 3) == false);
1353    try expect((A.val2 == 2) == true);
1354    const result2: S2 = .{ .a = !(A.val2 == 3), .b = (A.val1 == 2) };
1355    try expect(result2.a);
1356    try expect(!result2.b);
1357}