News for hackers. Stuff that matters.
Re:Packed structs in Zig make bit/flag sets trivial by flohofwoe on Tuesday August 30, 2022 @02:22AM (#32647206)
One area where this is still less flexible than regular bit masking is that quite often I want to access groups of bits as a value. For instance if the bits represent in/out pins on a chip emulator, sometimes I want to access unique data bus pins, and sometimes I want to set or get the data bus value.

Maybe Zig can handle this case with unions though, I haven't tried this yet (this would require that unions can work on the 'bit level' in packed structs).

Re:Packed structs in Zig make bit/flag sets trivial by Someone on Tuesday August 30, 2022 @03:43AM (#32647701)
Swift has OptionSet. See https://developer.apple.com/documentation/swift/optionset. It allows setting, testing, or clearing multiple fields with a nice syntax.

One thing that is a bit noisy is that you have to specify the bit index when you name the individual bits, as in (from that article):

  static let secondDay = ShippingOptions(rawValue: 1 << 1)
Upside from that is that it makes it clear what bit each value specifies, and won’t easily accidentally change them when you reorder definitions, or insert or remove them. I can see why they made that choice.

I also guess OptionSet could have been implemented in Swift in a third party library, whereas this Zig feature cannot.

I also think/guess neither language guarantees multiple bits would get read or written in one instruction. If your hardware needs that, you probably have to go down a level, or look at the disassembly of your code to check what your compiler did.

Re:Packed structs in Zig make bit/flag sets trivial by elcritch on Tuesday August 30, 2022 @02:59AM (#32647425)
I've come to really like Nim's built-in `set` type for that sorta scenario. It's just a bit-vector but it took me months before I realized that. You can cast an `int32` to a `set[MyEnum]` and be able to do set unions, differences, etc. Makes it easy to define a mask just by `const myMask = {A, B, E}`.

Making a Zig BitSet would probably be doable, for those cases where bitfields are overkill.

1: https://nim-lang.org/docs/manual.html#types-set-type

Re:Packed structs in Zig make bit/flag sets trivial by Comevius on Tuesday August 30, 2022 @07:10AM (#32648901)
You can do this and more in Zig. The only caveat is that for MMIO you need a volatile pointer.

https://www.scattered-thoughts.net/writing/mmio-in-zig/

It gets tricky if you need more control over loads and stores, or if there are different address spaces.

Re:Packed structs in Zig make bit/flag sets trivial by alphazino on Tuesday August 30, 2022 @03:21AM (#32647566)
I don't have experience with this area, but...

> this would require that unions can work on the 'bit level' in packed structs

Just as Zig has packed structs, it also has packed unions. So that part shouldn't be an issue.

Re:Packed structs in Zig make bit/flag sets trivial by AndyKelley on Tuesday August 30, 2022 @09:47PM (#32657409)
`@bitCast` addresses this use case:

    const std = @import("std");
    const expect = std.testing.expect;

    test {
        const group1: P = .{ .a = true, .b = true };
        const group2: P = .{ .c = true };
        const group3 = @bitCast(P, @bitCast(u4, group1) | @bitCast(u4, group2));
        try expect(group3.a);
        try expect(group3.b);
        try expect(group3.c);
        try expect(!group3.d);
    }

    const P = packed struct {
        a: bool = false,
        b: bool = false,
        c: bool = false,
        d: bool = false,
    };