DIP: add Bit Fields

Jonathan M Davis newsgroup.d at jmdavisprog.com
Fri Mar 8 09:10:38 UTC 2024


On Thursday, March 7, 2024 7:37:02 PM MST Walter Bright via dip.development 
wrote:
> The inconsistency of C bitfield layout is far less important than it is made
> out to be. Other inconsistencies C has: char/short/int/long sizes,
> float/double/longdouble behaviors, 1s or 2s complement arithmetic, field
> alignment and endianness. Even the signed-ness of chars is
> implementation-defined. D matches that behavior of the associated C
> compiler. Living with that is normal.

Yeah, but with the D types, we've mostly tried to fix that (e.g. making
char/short/int/long have fixed sizes), and D defines char, wchar, and dchar
all as being unsigned. We have enough compatibility to define aliases for
the C types and use those in bindings, but normal D code doesn't have to
deal with the issue.

bviously, there are some cases where we're forced to do the same as C even
when we might prefer not to, but we have managed to avoid some of C's
mistakes in normal D code in a number of cases while still having extern(C)
work.

> The gdc and ldc backends are written in C++. D bitfields would enable
> bitfields to be used in the D front end, and the backends can use them
> effortlessly (should be no problem for dtoh).
>
> An important feature of D is interoperability with C (and to some extent
> C++). Reducing the friction as much as we reasonably can will lower the
> barriers to D adoption. It means D code can co-exist peacefully in the same
> binary. When gdc and ldc are ported to a different platform, with different
> C bitfield layouts, it will still *effortlessly* work correctly.
>
> I like effortlessly.

Well, I guess that structs don't technically have extern(C) or extern(D) on
them, which makes this harder (structs and classes do with extern(C++), but
that doesn't help with C). Otherwise, the obvious thing would be to just use
the C behavior in structs / classes that are extern(C) or extern(C++) and
use well-defined, cross-platform behavior with extern(D) types, but it's the
functions that are extern(*), not the types.

However, the next thing that comes to mind would be to use a pragma or
attribute to control it. Then you could mark whether the bitfield member
would be C-compatible or not. If we really wanted to, we could even reuse
extern(C) / extern(C++) (which would then work well with files putting
extern(C): at the top like we often do in druntime), though I don't know how
desirable that is.

Still, if we have a way to tell the compiler whether we want bitfields to be
C-compatible or not, then we can have the C behavior where we need it and
better behavior for D everywhere else.

And it seems like it would be kind of bad to give the C-compatible version
the nice syntax for bitfields while requiring that D code that wants
consistent behavior use std.bitmanip's bitfelds instead, since that's going
to encourage folks to use the C bitfields when they arguably shouldn't be.
We need them for compatibility, but if at all reasonably possible, we should
be doing the better thing with normal D code.

- Jonathan M Davis





More information about the dip.development mailing list