zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

blob a8665a02 (36128B) - Raw


      1 const std = @import("std");
      2 const builtin = @import("builtin");
      3 const assert = std.debug.assert;
      4 const expect = std.testing.expect;
      5 const expectEqual = std.testing.expectEqual;
      6 const native_endian = builtin.cpu.arch.endian();
      7 
      8 test "flags in packed structs" {
      9     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
     10 
     11     const Flags1 = packed struct {
     12         // first 8 bits
     13         b0_0: u1,
     14         b0_1: u1,
     15         b0_2: u1,
     16         b0_3: u1,
     17         b0_4: u1,
     18         b0_5: u1,
     19         b0_6: u1,
     20         b0_7: u1,
     21 
     22         // 7 more bits
     23         b1_0: u1,
     24         b1_1: u1,
     25         b1_2: u1,
     26         b1_3: u1,
     27         b1_4: u1,
     28         b1_5: u1,
     29         b1_6: u1,
     30 
     31         // some padding to fill to 24 bits
     32         _: u9,
     33     };
     34 
     35     try expectEqual(@sizeOf(u24), @sizeOf(Flags1));
     36     try expectEqual(24, @bitSizeOf(Flags1));
     37 
     38     const Flags2 = packed struct {
     39         // byte 0
     40         b0_0: u1,
     41         b0_1: u1,
     42         b0_2: u1,
     43         b0_3: u1,
     44         b0_4: u1,
     45         b0_5: u1,
     46         b0_6: u1,
     47         b0_7: u1,
     48 
     49         // partial byte 1 (but not 8 bits)
     50         b1_0: u1,
     51         b1_1: u1,
     52         b1_2: u1,
     53         b1_3: u1,
     54         b1_4: u1,
     55         b1_5: u1,
     56         b1_6: u1,
     57 
     58         // some padding that should yield @sizeOf(Flags2) == 4
     59         _: u10,
     60     };
     61 
     62     try expectEqual(@sizeOf(u25), @sizeOf(Flags2));
     63     try expectEqual(25, @bitSizeOf(Flags2));
     64 
     65     const Flags3 = packed struct {
     66         // byte 0
     67         b0_0: u1,
     68         b0_1: u1,
     69         b0_2: u1,
     70         b0_3: u1,
     71         b0_4: u1,
     72         b0_5: u1,
     73         b0_6: u1,
     74         b0_7: u1,
     75 
     76         // byte 1
     77         b1_0: u1,
     78         b1_1: u1,
     79         b1_2: u1,
     80         b1_3: u1,
     81         b1_4: u1,
     82         b1_5: u1,
     83         b1_6: u1,
     84         b1_7: u1,
     85 
     86         // some padding that should yield @sizeOf(Flags2) == 4
     87         _: u16, // it works, if the padding is 8-based
     88     };
     89 
     90     try expectEqual(@sizeOf(u32), @sizeOf(Flags3));
     91     try expectEqual(32, @bitSizeOf(Flags3));
     92 }
     93 
     94 test "consistent size of packed structs" {
     95     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
     96 
     97     const TxData1 = packed struct { data: u8, _23: u23, full: bool = false };
     98     const TxData2 = packed struct { data: u9, _22: u22, full: bool = false };
     99 
    100     const register_size_bits = 32;
    101     const register_size_bytes = @sizeOf(u32);
    102 
    103     try expectEqual(register_size_bits, @bitSizeOf(TxData1));
    104     try expectEqual(register_size_bytes, @sizeOf(TxData1));
    105 
    106     try expectEqual(register_size_bits, @bitSizeOf(TxData2));
    107     try expectEqual(register_size_bytes, @sizeOf(TxData2));
    108 
    109     const TxData4 = packed struct { a: u32, b: u24 };
    110     const TxData6 = packed struct { a: u24, b: u32 };
    111 
    112     const expectedBitSize = 56;
    113     const expectedByteSize = @sizeOf(u56);
    114 
    115     try expectEqual(expectedBitSize, @bitSizeOf(TxData4));
    116     try expectEqual(expectedByteSize, @sizeOf(TxData4));
    117 
    118     try expectEqual(expectedBitSize, @bitSizeOf(TxData6));
    119     try expectEqual(expectedByteSize, @sizeOf(TxData6));
    120 }
    121 
    122 test "correct sizeOf and offsets in packed structs" {
    123     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
    124     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
    125     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    126     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    127 
    128     const PStruct = packed struct {
    129         bool_a: bool,
    130         bool_b: bool,
    131         bool_c: bool,
    132         bool_d: bool,
    133         bool_e: bool,
    134         bool_f: bool,
    135         u1_a: u1,
    136         bool_g: bool,
    137         u1_b: u1,
    138         u3_a: u3,
    139         u10_a: u10,
    140         u10_b: u10,
    141     };
    142     try expectEqual(0, @offsetOf(PStruct, "bool_a"));
    143     try expectEqual(0, @bitOffsetOf(PStruct, "bool_a"));
    144     try expectEqual(0, @offsetOf(PStruct, "bool_b"));
    145     try expectEqual(1, @bitOffsetOf(PStruct, "bool_b"));
    146     try expectEqual(0, @offsetOf(PStruct, "bool_c"));
    147     try expectEqual(2, @bitOffsetOf(PStruct, "bool_c"));
    148     try expectEqual(0, @offsetOf(PStruct, "bool_d"));
    149     try expectEqual(3, @bitOffsetOf(PStruct, "bool_d"));
    150     try expectEqual(0, @offsetOf(PStruct, "bool_e"));
    151     try expectEqual(4, @bitOffsetOf(PStruct, "bool_e"));
    152     try expectEqual(0, @offsetOf(PStruct, "bool_f"));
    153     try expectEqual(5, @bitOffsetOf(PStruct, "bool_f"));
    154     try expectEqual(0, @offsetOf(PStruct, "u1_a"));
    155     try expectEqual(6, @bitOffsetOf(PStruct, "u1_a"));
    156     try expectEqual(0, @offsetOf(PStruct, "bool_g"));
    157     try expectEqual(7, @bitOffsetOf(PStruct, "bool_g"));
    158     try expectEqual(1, @offsetOf(PStruct, "u1_b"));
    159     try expectEqual(8, @bitOffsetOf(PStruct, "u1_b"));
    160     try expectEqual(1, @offsetOf(PStruct, "u3_a"));
    161     try expectEqual(9, @bitOffsetOf(PStruct, "u3_a"));
    162     try expectEqual(1, @offsetOf(PStruct, "u10_a"));
    163     try expectEqual(12, @bitOffsetOf(PStruct, "u10_a"));
    164     try expectEqual(2, @offsetOf(PStruct, "u10_b"));
    165     try expectEqual(22, @bitOffsetOf(PStruct, "u10_b"));
    166     try expectEqual(4, @sizeOf(PStruct));
    167 
    168     if (native_endian == .little) {
    169         const s1 = @as(PStruct, @bitCast(@as(u32, 0x12345678)));
    170         try expectEqual(false, s1.bool_a);
    171         try expectEqual(false, s1.bool_b);
    172         try expectEqual(false, s1.bool_c);
    173         try expectEqual(true, s1.bool_d);
    174         try expectEqual(true, s1.bool_e);
    175         try expectEqual(true, s1.bool_f);
    176         try expectEqual(@as(u1, 1), s1.u1_a);
    177         try expectEqual(false, s1.bool_g);
    178         try expectEqual(@as(u1, 0), s1.u1_b);
    179         try expectEqual(@as(u3, 3), s1.u3_a);
    180         try expectEqual(@as(u10, 0b1101000101), s1.u10_a);
    181         try expectEqual(@as(u10, 0b0001001000), s1.u10_b);
    182 
    183         const s2 = @as(packed struct { x: u1, y: u7, z: u24 }, @bitCast(@as(u32, 0xd5c71ff4)));
    184         try expectEqual(@as(u1, 0), s2.x);
    185         try expectEqual(@as(u7, 0b1111010), s2.y);
    186         try expectEqual(@as(u24, 0xd5c71f), s2.z);
    187     }
    188 }
    189 
    190 test "nested packed structs" {
    191     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
    192     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
    193     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    194     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    195 
    196     const S1 = packed struct { a: u8, b: u8, c: u8 };
    197 
    198     const S2 = packed struct { d: u8, e: u8, f: u8 };
    199 
    200     const S3 = packed struct { x: S1, y: S2 };
    201     const S3Padded = packed struct { s3: S3, pad: u16 };
    202 
    203     try expectEqual(48, @bitSizeOf(S3));
    204     try expectEqual(@sizeOf(u48), @sizeOf(S3));
    205 
    206     try expectEqual(3, @offsetOf(S3, "y"));
    207     try expectEqual(24, @bitOffsetOf(S3, "y"));
    208 
    209     if (native_endian == .little) {
    210         const s3 = @as(S3Padded, @bitCast(@as(u64, 0xe952d5c71ff4))).s3;
    211         try expectEqual(@as(u8, 0xf4), s3.x.a);
    212         try expectEqual(@as(u8, 0x1f), s3.x.b);
    213         try expectEqual(@as(u8, 0xc7), s3.x.c);
    214         try expectEqual(@as(u8, 0xd5), s3.y.d);
    215         try expectEqual(@as(u8, 0x52), s3.y.e);
    216         try expectEqual(@as(u8, 0xe9), s3.y.f);
    217     }
    218 
    219     const S4 = packed struct { a: i32, b: i8 };
    220     const S5 = packed struct { a: i32, b: i8, c: S4 };
    221     const S6 = packed struct { a: i32, b: S4, c: i8 };
    222 
    223     const expectedBitSize = 80;
    224     const expectedByteSize = @sizeOf(u80);
    225     try expectEqual(expectedBitSize, @bitSizeOf(S5));
    226     try expectEqual(expectedByteSize, @sizeOf(S5));
    227     try expectEqual(expectedBitSize, @bitSizeOf(S6));
    228     try expectEqual(expectedByteSize, @sizeOf(S6));
    229 
    230     try expectEqual(5, @offsetOf(S5, "c"));
    231     try expectEqual(40, @bitOffsetOf(S5, "c"));
    232     try expectEqual(9, @offsetOf(S6, "c"));
    233     try expectEqual(72, @bitOffsetOf(S6, "c"));
    234 }
    235 
    236 test "regular in irregular packed struct" {
    237     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
    238     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
    239     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    240     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    241 
    242     const Irregular = packed struct {
    243         bar: Regular = Regular{},
    244         _: u24 = 0,
    245         pub const Regular = packed struct { a: u16 = 0, b: u8 = 0 };
    246     };
    247 
    248     var foo = Irregular{};
    249     foo.bar.a = 235;
    250     foo.bar.b = 42;
    251 
    252     try expectEqual(@as(u16, 235), foo.bar.a);
    253     try expectEqual(@as(u8, 42), foo.bar.b);
    254 }
    255 
    256 test "nested packed struct unaligned" {
    257     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
    258     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
    259     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    260     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    261     if (native_endian != .little) return error.SkipZigTest; // Byte aligned packed struct field pointers have not been implemented yet
    262 
    263     const S1 = packed struct {
    264         a: u4,
    265         b: u4,
    266         c: u8,
    267     };
    268     const S2 = packed struct {
    269         base: u8,
    270         p0: S1,
    271         bit0: u1,
    272         p1: packed struct {
    273             a: u8,
    274         },
    275         p2: packed struct {
    276             a: u7,
    277             b: u8,
    278         },
    279         p3: S1,
    280 
    281         var s: @This() = .{
    282             .base = 1,
    283             .p0 = .{ .a = 2, .b = 3, .c = 4 },
    284             .bit0 = 0,
    285             .p1 = .{ .a = 5 },
    286             .p2 = .{ .a = 6, .b = 7 },
    287             .p3 = .{ .a = 8, .b = 9, .c = 10 },
    288         };
    289     };
    290 
    291     try expect(S2.s.base == 1);
    292     try expect(S2.s.p0.a == 2);
    293     try expect(S2.s.p0.b == 3);
    294     try expect(S2.s.p0.c == 4);
    295     try expect(S2.s.bit0 == 0);
    296     try expect(S2.s.p1.a == 5);
    297     try expect(S2.s.p2.a == 6);
    298     try expect(S2.s.p2.b == 7);
    299     try expect(S2.s.p3.a == 8);
    300     try expect(S2.s.p3.b == 9);
    301     try expect(S2.s.p3.c == 10);
    302 
    303     const S3 = packed struct {
    304         pad: u8,
    305         v: u2,
    306         s: packed struct {
    307             v: u3,
    308             s: packed struct {
    309                 v: u2,
    310                 s: packed struct {
    311                     bit0: u1,
    312                     byte: u8,
    313                     bit1: u1,
    314                 },
    315             },
    316         },
    317         var v0: @This() = .{ .pad = 0, .v = 1, .s = .{ .v = 2, .s = .{ .v = 3, .s = .{ .bit0 = 0, .byte = 4, .bit1 = 1 } } } };
    318     };
    319 
    320     try expect(S3.v0.v == 1);
    321     try expect(S3.v0.s.v == 2);
    322     try expect(S3.v0.s.s.v == 3);
    323     try expect(S3.v0.s.s.s.bit0 == 0);
    324     try expect(S3.v0.s.s.s.byte == 4);
    325     try expect(S3.v0.s.s.s.bit1 == 1);
    326 }
    327 
    328 test "byte-aligned field pointer offsets" {
    329     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
    330     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
    331     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    332     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    333 
    334     const S = struct {
    335         const A = packed struct {
    336             a: u8,
    337             b: u8,
    338             c: u8,
    339             d: u8,
    340         };
    341 
    342         const B = packed struct {
    343             a: u16,
    344             b: u16,
    345         };
    346 
    347         fn doTheTest() !void {
    348             var a: A = .{
    349                 .a = 1,
    350                 .b = 2,
    351                 .c = 3,
    352                 .d = 4,
    353             };
    354             switch (comptime builtin.cpu.arch.endian()) {
    355                 .little => {
    356                     comptime assert(@TypeOf(&a.a) == *align(4) u8);
    357                     comptime assert(@TypeOf(&a.b) == *u8);
    358                     comptime assert(@TypeOf(&a.c) == *align(2) u8);
    359                     comptime assert(@TypeOf(&a.d) == *u8);
    360                 },
    361                 .big => {
    362                     // TODO re-evaluate packed struct endianness
    363                     comptime assert(@TypeOf(&a.a) == *align(4:0:4) u8);
    364                     comptime assert(@TypeOf(&a.b) == *align(4:8:4) u8);
    365                     comptime assert(@TypeOf(&a.c) == *align(4:16:4) u8);
    366                     comptime assert(@TypeOf(&a.d) == *align(4:24:4) u8);
    367                 },
    368             }
    369             try expect(a.a == 1);
    370             try expect(a.b == 2);
    371             try expect(a.c == 3);
    372             try expect(a.d == 4);
    373 
    374             a.a += 1;
    375             try expect(a.a == 2);
    376             try expect(a.b == 2);
    377             try expect(a.c == 3);
    378             try expect(a.d == 4);
    379 
    380             a.b += 1;
    381             try expect(a.a == 2);
    382             try expect(a.b == 3);
    383             try expect(a.c == 3);
    384             try expect(a.d == 4);
    385 
    386             a.c += 1;
    387             try expect(a.a == 2);
    388             try expect(a.b == 3);
    389             try expect(a.c == 4);
    390             try expect(a.d == 4);
    391 
    392             a.d += 1;
    393             try expect(a.a == 2);
    394             try expect(a.b == 3);
    395             try expect(a.c == 4);
    396             try expect(a.d == 5);
    397 
    398             var b: B = .{
    399                 .a = 1,
    400                 .b = 2,
    401             };
    402             switch (comptime builtin.cpu.arch.endian()) {
    403                 .little => {
    404                     comptime assert(@TypeOf(&b.a) == *align(4) u16);
    405                     comptime assert(@TypeOf(&b.b) == *u16);
    406                 },
    407                 .big => {
    408                     comptime assert(@TypeOf(&b.a) == *align(4:0:4) u16);
    409                     comptime assert(@TypeOf(&b.b) == *align(4:16:4) u16);
    410                 },
    411             }
    412             try expect(b.a == 1);
    413             try expect(b.b == 2);
    414 
    415             b.a += 1;
    416             try expect(b.a == 2);
    417             try expect(b.b == 2);
    418 
    419             b.b += 1;
    420             try expect(b.a == 2);
    421             try expect(b.b == 3);
    422         }
    423     };
    424 
    425     try S.doTheTest();
    426     try comptime S.doTheTest();
    427 }
    428 
    429 test "nested packed struct field pointers" {
    430     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
    431     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
    432     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    433     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    434     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // ubsan unaligned pointer access
    435     if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
    436     if (native_endian != .little) return error.SkipZigTest; // Byte aligned packed struct field pointers have not been implemented yet
    437 
    438     const S2 = packed struct {
    439         base: u8,
    440         p0: packed struct {
    441             a: u4,
    442             b: u4,
    443             c: u8,
    444         },
    445         bit: u1,
    446         p1: packed struct {
    447             a: u7,
    448             b: u8,
    449         },
    450 
    451         var s: @This() = .{ .base = 1, .p0 = .{ .a = 2, .b = 3, .c = 4 }, .bit = 0, .p1 = .{ .a = 5, .b = 6 } };
    452     };
    453 
    454     const ptr_base = &S2.s.base;
    455     const ptr_p0_a = &S2.s.p0.a;
    456     const ptr_p0_b = &S2.s.p0.b;
    457     const ptr_p0_c = &S2.s.p0.c;
    458     const ptr_p1_a = &S2.s.p1.a;
    459     const ptr_p1_b = &S2.s.p1.b;
    460     try expectEqual(@as(u8, 1), ptr_base.*);
    461     try expectEqual(@as(u4, 2), ptr_p0_a.*);
    462     try expectEqual(@as(u4, 3), ptr_p0_b.*);
    463     try expectEqual(@as(u8, 4), ptr_p0_c.*);
    464     try expectEqual(@as(u7, 5), ptr_p1_a.*);
    465     try expectEqual(@as(u8, 6), ptr_p1_b.*);
    466 }
    467 
    468 test "load pointer from packed struct" {
    469     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
    470     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
    471     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    472     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    473 
    474     const A = struct {
    475         index: u16,
    476     };
    477     const B = packed struct {
    478         x: *A,
    479         y: u32,
    480     };
    481     var a: A = .{ .index = 123 };
    482     var b_list: []const B = &.{.{ .x = &a, .y = 99 }};
    483     for (b_list) |b| {
    484         var i = b.x.index;
    485         try expect(i == 123);
    486     }
    487 }
    488 
    489 test "@intFromPtr on a packed struct field" {
    490     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
    491     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
    492     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    493     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    494     if (native_endian != .little) return error.SkipZigTest;
    495 
    496     const S = struct {
    497         const P = packed struct {
    498             x: u8,
    499             y: u8,
    500             z: u32,
    501         };
    502 
    503         var p0: P = P{
    504             .x = 1,
    505             .y = 2,
    506             .z = 0,
    507         };
    508     };
    509     try expect(@intFromPtr(&S.p0.z) - @intFromPtr(&S.p0.x) == 2);
    510 }
    511 
    512 test "@intFromPtr on a packed struct field unaligned and nested" {
    513     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
    514     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
    515     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    516     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    517     if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
    518     if (native_endian != .little) return error.SkipZigTest; // Byte aligned packed struct field pointers have not been implemented yet
    519 
    520     const S1 = packed struct {
    521         a: u4,
    522         b: u4,
    523         c: u8,
    524     };
    525     const S2 = packed struct {
    526         base: u8,
    527         p0: S1,
    528         bit0: u1,
    529         p1: packed struct {
    530             a: u8,
    531         },
    532         p2: packed struct {
    533             a: u7,
    534             b: u8,
    535         },
    536         p3: S1,
    537 
    538         var s: @This() = .{
    539             .base = 1,
    540             .p0 = .{ .a = 2, .b = 3, .c = 4 },
    541             .bit0 = 0,
    542             .p1 = .{ .a = 5 },
    543             .p2 = .{ .a = 6, .b = 7 },
    544             .p3 = .{ .a = 8, .b = 9, .c = 10 },
    545         };
    546     };
    547 
    548     switch (comptime @alignOf(S2)) {
    549         4 => {
    550             comptime assert(@TypeOf(&S2.s.base) == *align(4) u8);
    551             comptime assert(@TypeOf(&S2.s.p0.a) == *align(1:0:2) u4);
    552             comptime assert(@TypeOf(&S2.s.p0.b) == *align(1:4:2) u4);
    553             comptime assert(@TypeOf(&S2.s.p0.c) == *u8);
    554             comptime assert(@TypeOf(&S2.s.bit0) == *align(4:24:8) u1);
    555             comptime assert(@TypeOf(&S2.s.p1.a) == *align(4:25:8) u8);
    556             comptime assert(@TypeOf(&S2.s.p2.a) == *align(4:33:8) u7);
    557             comptime assert(@TypeOf(&S2.s.p2.b) == *u8);
    558             comptime assert(@TypeOf(&S2.s.p3.a) == *align(2:0:2) u4);
    559             comptime assert(@TypeOf(&S2.s.p3.b) == *align(2:4:2) u4);
    560             comptime assert(@TypeOf(&S2.s.p3.c) == *u8);
    561         },
    562         8 => {
    563             comptime assert(@TypeOf(&S2.s.base) == *align(8) u8);
    564             comptime assert(@TypeOf(&S2.s.p0.a) == *align(1:0:2) u4);
    565             comptime assert(@TypeOf(&S2.s.p0.b) == *align(1:4:2) u4);
    566             comptime assert(@TypeOf(&S2.s.p0.c) == *u8);
    567             comptime assert(@TypeOf(&S2.s.bit0) == *align(8:24:8) u1);
    568             comptime assert(@TypeOf(&S2.s.p1.a) == *align(8:25:8) u8);
    569             comptime assert(@TypeOf(&S2.s.p2.a) == *align(8:33:8) u7);
    570             comptime assert(@TypeOf(&S2.s.p2.b) == *u8);
    571             comptime assert(@TypeOf(&S2.s.p3.a) == *align(2:0:2) u4);
    572             comptime assert(@TypeOf(&S2.s.p3.b) == *align(2:4:2) u4);
    573             comptime assert(@TypeOf(&S2.s.p3.c) == *u8);
    574         },
    575         else => {},
    576     }
    577     try expect(@intFromPtr(&S2.s.base) - @intFromPtr(&S2.s) == 0);
    578     try expect(@intFromPtr(&S2.s.p0.a) - @intFromPtr(&S2.s) == 1);
    579     try expect(@intFromPtr(&S2.s.p0.b) - @intFromPtr(&S2.s) == 1);
    580     try expect(@intFromPtr(&S2.s.p0.c) - @intFromPtr(&S2.s) == 2);
    581     try expect(@intFromPtr(&S2.s.bit0) - @intFromPtr(&S2.s) == 0);
    582     try expect(@intFromPtr(&S2.s.p1.a) - @intFromPtr(&S2.s) == 0);
    583     try expect(@intFromPtr(&S2.s.p2.a) - @intFromPtr(&S2.s) == 0);
    584     try expect(@intFromPtr(&S2.s.p2.b) - @intFromPtr(&S2.s) == 5);
    585     try expect(@intFromPtr(&S2.s.p3.a) - @intFromPtr(&S2.s) == 6);
    586     try expect(@intFromPtr(&S2.s.p3.b) - @intFromPtr(&S2.s) == 6);
    587     try expect(@intFromPtr(&S2.s.p3.c) - @intFromPtr(&S2.s) == 7);
    588 
    589     const S3 = packed struct {
    590         pad: u8,
    591         v: u2,
    592         s: packed struct {
    593             v: u3,
    594             s: packed struct {
    595                 v: u2,
    596                 s: packed struct {
    597                     bit0: u1,
    598                     byte: u8,
    599                     bit1: u1,
    600                 },
    601             },
    602         },
    603         var v0: @This() = .{ .pad = 0, .v = 1, .s = .{ .v = 2, .s = .{ .v = 3, .s = .{ .bit0 = 0, .byte = 4, .bit1 = 1 } } } };
    604     };
    605 
    606     comptime assert(@TypeOf(&S3.v0.v) == *align(4:8:4) u2);
    607     comptime assert(@TypeOf(&S3.v0.s.v) == *align(4:10:4) u3);
    608     comptime assert(@TypeOf(&S3.v0.s.s.v) == *align(4:13:4) u2);
    609     comptime assert(@TypeOf(&S3.v0.s.s.s.bit0) == *align(4:15:4) u1);
    610     comptime assert(@TypeOf(&S3.v0.s.s.s.byte) == *align(2) u8);
    611     comptime assert(@TypeOf(&S3.v0.s.s.s.bit1) == *align(4:24:4) u1);
    612     try expect(@intFromPtr(&S3.v0.v) - @intFromPtr(&S3.v0) == 0);
    613     try expect(@intFromPtr(&S3.v0.s) - @intFromPtr(&S3.v0) == 0);
    614     try expect(@intFromPtr(&S3.v0.s.v) - @intFromPtr(&S3.v0) == 0);
    615     try expect(@intFromPtr(&S3.v0.s.s) - @intFromPtr(&S3.v0) == 0);
    616     try expect(@intFromPtr(&S3.v0.s.s.v) - @intFromPtr(&S3.v0) == 0);
    617     try expect(@intFromPtr(&S3.v0.s.s.s) - @intFromPtr(&S3.v0) == 0);
    618     try expect(@intFromPtr(&S3.v0.s.s.s.bit0) - @intFromPtr(&S3.v0) == 0);
    619     try expect(@intFromPtr(&S3.v0.s.s.s.byte) - @intFromPtr(&S3.v0) == 2);
    620     try expect(@intFromPtr(&S3.v0.s.s.s.bit1) - @intFromPtr(&S3.v0) == 0);
    621 }
    622 
    623 test "packed struct fields modification" {
    624     // Originally reported at https://github.com/ziglang/zig/issues/16615
    625     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    626 
    627     const Small = packed struct {
    628         val: u8 = 0,
    629         lo: u4 = 0,
    630         hi: u4 = 0,
    631 
    632         var p: @This() = undefined;
    633     };
    634     Small.p = .{
    635         .val = 0x12,
    636         .lo = 3,
    637         .hi = 4,
    638     };
    639     try expect(@as(u16, @bitCast(Small.p)) == 0x4312);
    640 
    641     Small.p.val -= Small.p.lo;
    642     Small.p.val += Small.p.hi;
    643     Small.p.hi -= Small.p.lo;
    644     try expect(@as(u16, @bitCast(Small.p)) == 0x1313);
    645 }
    646 
    647 test "optional pointer in packed struct" {
    648     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
    649     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
    650     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    651     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    652 
    653     const T = packed struct { ptr: ?*const u8 };
    654     var n: u8 = 0;
    655     const x = T{ .ptr = &n };
    656     try expect(x.ptr.? == &n);
    657 }
    658 
    659 test "nested packed struct field access test" {
    660     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
    661     if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO packed structs larger than 64 bits
    662     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
    663     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
    664     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    665     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    666     if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
    667 
    668     const Vec2 = packed struct {
    669         x: f32,
    670         y: f32,
    671     };
    672 
    673     const Vec3 = packed struct {
    674         x: f32,
    675         y: f32,
    676         z: f32,
    677     };
    678 
    679     const NestedVec2 = packed struct {
    680         nested: Vec2,
    681     };
    682 
    683     const NestedVec3 = packed struct {
    684         nested: Vec3,
    685     };
    686 
    687     const vec2 = Vec2{
    688         .x = 1.0,
    689         .y = 2.0,
    690     };
    691 
    692     try std.testing.expectEqual(vec2.x, 1.0);
    693     try std.testing.expectEqual(vec2.y, 2.0);
    694 
    695     var vec2_o: Vec2 = undefined;
    696     const vec2_o_ptr: *Vec2 = &vec2_o;
    697     vec2_o_ptr.* = vec2;
    698 
    699     try std.testing.expectEqual(vec2_o.x, 1.0);
    700     try std.testing.expectEqual(vec2_o.y, 2.0);
    701 
    702     const nested_vec2 = NestedVec2{
    703         .nested = Vec2{
    704             .x = 1.0,
    705             .y = 2.0,
    706         },
    707     };
    708 
    709     try std.testing.expectEqual(nested_vec2.nested.x, 1.0);
    710     try std.testing.expectEqual(nested_vec2.nested.y, 2.0);
    711 
    712     var nested_o: NestedVec2 = undefined;
    713     const nested_o_ptr: *NestedVec2 = &nested_o;
    714     nested_o_ptr.* = nested_vec2;
    715 
    716     try std.testing.expectEqual(nested_o.nested.x, 1.0);
    717     try std.testing.expectEqual(nested_o.nested.y, 2.0);
    718 
    719     const vec3 = Vec3{
    720         .x = 1.0,
    721         .y = 2.0,
    722         .z = 3.0,
    723     };
    724 
    725     try std.testing.expectEqual(vec3.x, 1.0);
    726     try std.testing.expectEqual(vec3.y, 2.0);
    727     try std.testing.expectEqual(vec3.z, 3.0);
    728 
    729     var vec3_o: Vec3 = undefined;
    730     const vec3_o_ptr: *Vec3 = &vec3_o;
    731     vec3_o_ptr.* = vec3;
    732 
    733     try std.testing.expectEqual(vec3_o.x, 1.0);
    734     try std.testing.expectEqual(vec3_o.y, 2.0);
    735     try std.testing.expectEqual(vec3_o.z, 3.0);
    736 
    737     const nested_vec3 = NestedVec3{
    738         .nested = Vec3{
    739             .x = 1.0,
    740             .y = 2.0,
    741             .z = 3.0,
    742         },
    743     };
    744 
    745     try std.testing.expectEqual(nested_vec3.nested.x, 1.0);
    746     try std.testing.expectEqual(nested_vec3.nested.y, 2.0);
    747     try std.testing.expectEqual(nested_vec3.nested.z, 3.0);
    748 
    749     var nested_vec3_o: NestedVec3 = undefined;
    750     const nested_vec3_o_ptr: *NestedVec3 = &nested_vec3_o;
    751     nested_vec3_o_ptr.* = nested_vec3;
    752 
    753     try std.testing.expectEqual(nested_vec3_o.nested.x, 1.0);
    754     try std.testing.expectEqual(nested_vec3_o.nested.y, 2.0);
    755     try std.testing.expectEqual(nested_vec3_o.nested.z, 3.0);
    756 
    757     const hld = packed struct {
    758         c: u64,
    759         d: u32,
    760     };
    761 
    762     const mld = packed struct {
    763         h: u64,
    764         i: u64,
    765     };
    766 
    767     const a = packed struct {
    768         b: hld,
    769         g: mld,
    770     };
    771 
    772     var arg = a{ .b = hld{ .c = 1, .d = 2 }, .g = mld{ .h = 6, .i = 8 } };
    773     try std.testing.expect(arg.b.c == 1);
    774     try std.testing.expect(arg.b.d == 2);
    775     try std.testing.expect(arg.g.h == 6);
    776     try std.testing.expect(arg.g.i == 8);
    777 }
    778 
    779 test "nested packed struct at non-zero offset" {
    780     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    781     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    782 
    783     const Pair = packed struct(u24) {
    784         a: u16 = 0,
    785         b: u8 = 0,
    786     };
    787     const A = packed struct {
    788         p1: Pair,
    789         p2: Pair,
    790     };
    791 
    792     var k: u8 = 123;
    793     var v: A = .{
    794         .p1 = .{ .a = k + 1, .b = k },
    795         .p2 = .{ .a = k + 1, .b = k },
    796     };
    797 
    798     try expect(v.p1.a == k + 1 and v.p1.b == k);
    799     try expect(v.p2.a == k + 1 and v.p2.b == k);
    800 
    801     v.p2.a -= v.p1.a;
    802     v.p2.b -= v.p1.b;
    803     try expect(v.p2.a == 0 and v.p2.b == 0);
    804     try expect(v.p1.a == k + 1 and v.p1.b == k);
    805 }
    806 
    807 test "nested packed struct at non-zero offset 2" {
    808     if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
    809     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
    810     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
    811     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    812     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    813     if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO packed structs larger than 64 bits
    814     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
    815 
    816     const S = struct {
    817         const Pair = packed struct(u40) {
    818             a: u32 = 0,
    819             b: u8 = 0,
    820         };
    821         const A = packed struct {
    822             p1: Pair,
    823             p2: Pair,
    824             c: C,
    825         };
    826         const C = packed struct {
    827             p1: Pair,
    828             pad1: u5,
    829             p2: Pair,
    830             pad2: u3,
    831             last: i16,
    832         };
    833 
    834         fn doTheTest() !void {
    835             var k: u8 = 123;
    836             var v: A = .{
    837                 .p1 = .{ .a = k + 1, .b = k },
    838                 .p2 = .{ .a = k + 1, .b = k },
    839                 .c = .{
    840                     .pad1 = 11,
    841                     .pad2 = 2,
    842                     .p1 = .{ .a = k + 1, .b = k },
    843                     .p2 = .{ .a = k + 1, .b = k },
    844                     .last = -12345,
    845                 },
    846             };
    847 
    848             try expect(v.p1.a == k + 1 and v.p1.b == k);
    849             try expect(v.p2.a == k + 1 and v.p2.b == k);
    850             try expect(v.c.p2.a == k + 1 and v.c.p2.b == k);
    851             try expect(v.c.p2.a == k + 1 and v.c.p2.b == k);
    852             try expect(v.c.last == -12345);
    853             try expect(v.c.pad1 == 11 and v.c.pad2 == 2);
    854 
    855             v.p2.a -= v.p1.a;
    856             v.p2.b -= v.p1.b;
    857             v.c.p2.a -= v.c.p1.a;
    858             v.c.p2.b -= v.c.p1.b;
    859             v.c.last -|= 32000;
    860             try expect(v.p2.a == 0 and v.p2.b == 0);
    861             try expect(v.p1.a == k + 1 and v.p1.b == k);
    862             try expect(v.c.p2.a == 0 and v.c.p2.b == 0);
    863             try expect(v.c.p1.a == k + 1 and v.c.p1.b == k);
    864             try expect(v.c.last == -32768);
    865             try expect(v.c.pad1 == 11 and v.c.pad2 == 2);
    866         }
    867     };
    868 
    869     try S.doTheTest();
    870     try comptime S.doTheTest();
    871 }
    872 
    873 test "runtime init of unnamed packed struct type" {
    874     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
    875     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
    876     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    877     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    878 
    879     var z: u8 = 123;
    880     try (packed struct {
    881         x: u8,
    882         pub fn m(s: @This()) !void {
    883             try expect(s.x == 123);
    884         }
    885     }{ .x = z }).m();
    886 }
    887 
    888 test "packed struct passed to callconv(.C) function" {
    889     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
    890     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
    891     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    892     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    893 
    894     const S = struct {
    895         const Packed = packed struct {
    896             a: u16,
    897             b: bool = true,
    898             c: bool = true,
    899             d: u46 = 0,
    900         };
    901 
    902         fn foo(p: Packed, a1: u64, a2: u64, a3: u64, a4: u64, a5: u64) callconv(.C) bool {
    903             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;
    904         }
    905     };
    906     const result = S.foo(S.Packed{
    907         .a = 12345,
    908         .b = true,
    909         .c = true,
    910     }, 5, 4, 3, 2, 1);
    911     try expect(result);
    912 }
    913 
    914 test "overaligned pointer to packed struct" {
    915     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
    916     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
    917     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    918     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    919 
    920     const S = packed struct { a: u32, b: u32 };
    921     var foo: S align(4) = .{ .a = 123, .b = 456 };
    922     const ptr: *align(4) S = &foo;
    923     switch (comptime builtin.cpu.arch.endian()) {
    924         .little => {
    925             const ptr_to_b: *u32 = &ptr.b;
    926             try expect(ptr_to_b.* == 456);
    927         },
    928         .big => {
    929             // Byte aligned packed struct field pointers have not been implemented yet.
    930             const ptr_to_a: *align(4:0:8) u32 = &ptr.a;
    931             try expect(ptr_to_a.* == 123);
    932         },
    933     }
    934 }
    935 
    936 test "packed struct initialized in bitcast" {
    937     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
    938     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
    939     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    940     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    941 
    942     const T = packed struct { val: u8 };
    943     var val: u8 = 123;
    944     const t = @as(u8, @bitCast(T{ .val = val }));
    945     try expect(t == val);
    946 }
    947 
    948 test "pointer to container level packed struct field" {
    949     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
    950     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
    951     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    952     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    953 
    954     const S = packed struct(u32) {
    955         test_bit: bool,
    956         someother_data: u12,
    957         other_test_bit: bool,
    958         someother_more_different_data: u12,
    959         other_bits: packed struct(u6) {
    960             enable_1: bool,
    961             enable_2: bool,
    962             enable_3: bool,
    963             enable_4: bool,
    964             enable_5: bool,
    965             enable_6: bool,
    966         },
    967         var arr = [_]u32{0} ** 2;
    968     };
    969     @as(*S, @ptrCast(&S.arr[0])).other_bits.enable_3 = true;
    970     try expect(S.arr[0] == 0x10000000);
    971 }
    972 
    973 test "store undefined to packed result location" {
    974     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
    975     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
    976     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    977 
    978     var x: u4 = 0;
    979     var s = packed struct { x: u4, y: u4 }{ .x = x, .y = if (x > 0) x else undefined };
    980     try expectEqual(x, s.x);
    981 }
    982 
    983 test "bitcast back and forth" {
    984     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    985 
    986     // Originally reported at https://github.com/ziglang/zig/issues/9914
    987     const S = packed struct { one: u6, two: u1 };
    988     const s = S{ .one = 0b110101, .two = 0b1 };
    989     const u: u7 = @bitCast(s);
    990     const s2: S = @bitCast(u);
    991     try expect(s.one == s2.one);
    992     try expect(s.two == s2.two);
    993 }
    994 
    995 test "field access of packed struct smaller than its abi size inside struct initialized with rls" {
    996     // Originally reported at https://github.com/ziglang/zig/issues/14200
    997     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    998 
    999     const S = struct {
   1000         ps: packed struct { x: i2, y: i2 },
   1001 
   1002         fn init(cond: bool) @This() {
   1003             return .{ .ps = .{ .x = 0, .y = if (cond) 1 else 0 } };
   1004         }
   1005     };
   1006 
   1007     var s = S.init(true);
   1008     // note: this bug is triggered by the == operator, expectEqual will hide it
   1009     try expect(@as(i2, 0) == s.ps.x);
   1010     try expect(@as(i2, 1) == s.ps.y);
   1011 }
   1012 
   1013 test "modify nested packed struct aligned field" {
   1014     // Originally reported at https://github.com/ziglang/zig/issues/14632
   1015     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
   1016     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
   1017     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
   1018     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
   1019 
   1020     const Options = packed struct {
   1021         foo: bool = false,
   1022         bar: bool = false,
   1023         pretty_print: packed struct {
   1024             enabled: bool = false,
   1025             num_spaces: u4 = 4,
   1026             space_char: enum { space, tab } = .space,
   1027             indent: u8 = 0,
   1028         } = .{},
   1029         baz: bool = false,
   1030     };
   1031 
   1032     var opts = Options{};
   1033     opts.pretty_print.indent += 1;
   1034     try std.testing.expectEqual(@as(u17, 0b00000000100100000), @bitCast(opts));
   1035     try std.testing.expect(!opts.foo);
   1036     try std.testing.expect(!opts.bar);
   1037     try std.testing.expect(!opts.pretty_print.enabled);
   1038     try std.testing.expectEqual(@as(u4, 4), opts.pretty_print.num_spaces);
   1039     try std.testing.expectEqual(@as(u8, 1), opts.pretty_print.indent);
   1040     try std.testing.expect(!opts.baz);
   1041 }
   1042 
   1043 test "assigning packed struct inside another packed struct" {
   1044     // Originally reported at https://github.com/ziglang/zig/issues/9674
   1045     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
   1046 
   1047     const S = struct {
   1048         const Inner = packed struct {
   1049             bits: u3,
   1050             more_bits: u6,
   1051         };
   1052 
   1053         const Outer = packed struct {
   1054             padding: u5,
   1055             inner: Inner,
   1056         };
   1057         fn t(inner: Inner) void {
   1058             r.inner = inner;
   1059         }
   1060 
   1061         var mem: Outer = undefined;
   1062         var r: *volatile Outer = &mem;
   1063     };
   1064 
   1065     const val = S.Inner{ .bits = 1, .more_bits = 11 };
   1066     S.mem.padding = 0;
   1067     S.t(val);
   1068 
   1069     try expectEqual(val, S.mem.inner);
   1070     try expect(S.mem.padding == 0);
   1071 }