second draft: add Bitfields to D
Timon Gehr
timon.gehr at gmx.ch
Mon Apr 29 12:04:13 UTC 2024
On 4/29/24 08:44, Walter Bright wrote:
> On 4/28/2024 3:30 PM, Timon Gehr wrote:
>> However, I would still much prefer a solution that explicitly
>> introduces the underlying `int`, `uint`, `long` and `ulong` fields,
>> which would be the ones visible to introspection in a portable way, so
>> that introspection code does not really need to concern itself with
>> bitfields at all if it is not important and we do not break existing
>> introspection libraries, such as all serialization libraries.
>
> I doubt introspection libraries would break.
You are breaking even simple patterns like
`foreach(ref field;s.tupleof){ }`.
It would be a miracle if libraries did not break.
> If they are not checking
> for bitfields, but are just looking at .offsetof and the type, they'll
> interpret the bitfields as a union (which, in a way, is accurate).
> ...
No, it is not accurate.
> ...
>> I like that the members are not as cluttered. I guess maybe some
>> people still would like to access the underlying data (e.g., to
>> implement a pointer to bitfield as a struct with a pointer plus bit
>> offset and bit length, or something), so perhaps you could add a note
>> that explains how to do that.
>
> Pointer to bitfields will work just the same as they do in C. I don't
> understand what you're asking for.
> ...
Well, you can't take a pointer to a bitfield.
>> You forgot to say what `.tupleof` will do for a struct with bitfields
>> in it.
>
> They do exactly what you'd expect them to do:
>
> ```
> import std.stdio;
> struct S { int a:4, b:5; }
> void main()
> {
> S s;
> s.a = 7;
> s.b = 9;
> writeln(s.tupleof);
> }
> ```
> prints:
> ```
> 79
> ```
> It's not necessary to specify this,
Well, so far everything in `.tupleof` had an address.
It should at least be mentioned in the DIP, if nowhere else you should
put it in the breaking language changes section.
> because this behavior does not
> diverge from field access semantics.
There is a difference between a DIP (that can change the language) and
the specification (that can indeed be written in a way that does not
explicitly mention bitfields under the `.tupleof` documentation.)
> ...
>
>> I think it would be better to have such a `__traits` even just for
>> discoverability when people look at the `__traits` page to implement
>> some introspection code.
>
> There isn't for other members, it's just "allMembers".
> ...
Despite not being very relevant to what I was asking for, this is simply
untrue. `allMembers` gives you the members, and `.tupleof` gives you the
fields.
>
>>> testing to see if the address of a field can be taken, enables
>>> discovery of a bitfield.
>>
>> Not really, a field could be an `enum` field, and you cannot take the
>> address of that either. And if we ever add another feature that has
>> fields whose address can be taken, existing introspection code may
>> break. It is better to be explicit.
>
> An enum is distinguished by it not being possible to use .offsetof with it.
> ...
Well, if you are trying to deliberately make introspection unnecessarily
complicated, I guess that's your prerogative.
>
>>> The values of .max or .min enable determining the number of bits in a
>>> bitfield.
>> I do not like this a lot, it does not seem like the canonical way to
>> determine it. `.bitlength`?
>
> I agree it's a bit(!) jarring at first blush, but it's easy and
> perfectly reliable. 7 and 15 are always going to be a 4 bit field. We do
> a lot of introspection via indirect things like this.
> ...
All of those things are ugly hacks. This kind of brain teaser is how
metaprogramming works (or increasingly: used to work) in C++, but I
think it is not very wise to continue this tradition in D.
>
>>> The bit offset can be introspected by summing the number of bits in
>>> each preceding bitfield that has the same value of .offsetof.
>>
>> I think it would be much better to just add a `__trait` for this or
>> add something like `.bitoffsetof`. This is a) much more user friendly
>> and b) is a bit more likely to work reliably in practice. D currently
>> does not give any guarantees on the order you will see members when
>> using `__traits(allMembers, ...)`.
>
> I overlooked that bitfields can have holes in them, so probably
> something like .bitoffsetof is probably necessary.
Sounds good.
More information about the dip.development
mailing list