March 18
On 3/8/24 20:52, Walter Bright wrote:
> 
> There are two dominant schemes today, VC and gcc. I'm not aware of any other scheme for a modern C compiler (Digital Mars C emulates the VC layout). Even so, VC and gcc lay things out the same way for `int` bit fields. This is never going to change.

Well, if you believe this, why not specify the behavior?

Similarly, if you believe a specced-out `extern(D)` vs a "companion compiler" `extern(C)` would not make a difference anyway, why is it a concern to you that they could be accidentally confused?

And finally, why not just require an _explicit_ specification of the layout on the D side?

E.g., something like:

```d
int x {
    int a : 2;
    int b : 18;
    int c : 11;
    int : 1; // sign bit reserved
}
```

(x.a, x.b, etc.)


or perhaps even:

```d
int {
    int a : 2;
    int b : 18;
    int c : 11;
    int : 1; // sign bit reserved
}
```

Then make the compiler enforce that the fields add up to the size of the type. By default this is compatible with what VC and GCC do, and ImportC can just uniformly translate the imported C code to such an explicit layout spec. It will even be intuitive.

Just make it portable across machines with the same endianness, like the built-in integer types already are. This optimizes the user experience at the same time: It will usually be obvious how big a struct is, there will not be a need to add together the sizes of bit fields in order to figure out how things are laid out in memory.

In any case, the introspection story needs to be fixed. (Even just for the sake of introspecting structs originating in ImportC code.)

This would be so much better and improve ImportC at the same time.
March 23

On Thursday, 7 March 2024 at 04:26:56 UTC, Walter Bright wrote:

>

https://github.com/WalterBright/documents/blob/master/bitfields.md

Most of the complaints by the seasoned pros here are of the form: C bitfields are an implementation-defined mess, and we shouldn't copy them. I don't think this means we can't copy the good parts.

If I understand correctly, it's because C can do odd things with corner cases, not because it's doing insane things like storing bitfields in every other bit, etc.

So if "almost all C compilers" do the same thing, why not just define that thing, and say D does it this way? Why say we depend 100% on C compiler implementation whims? If the corner cases are problematic, ban the corner cases?

Pick the "right way", define it, and say "This works for most cases in all the C compilers we use, and if it doesn't, you have to figure it out yourself". I don't understand the problem with that. ImportC bitfields don't have to be the same. As you once told me, bitfields are not generally used for public API, because of the complications. So why do we need C compatibility in the first place?

C does some really dumb things (hindsight, etc.), and D didn't copy all those dumb things. We should continue to not do dumb things.

Bitfields should have __traits to go with them (e.g. __traits(bitSize, x) should return 4 for a 4-bit value). There is zero reason to hide what the compiler knows. I don't know if there are any more things needed, as you can use typeof to get the underlying type, and getting an address to the full bitfield can be done with a union.

There are other things that aren't specified in the proposal, such as the properties that work on other basic types: sizeof, offsetof, alignof.

-Steve

March 23

On Saturday, 23 March 2024 at 02:32:20 UTC, Steven Schveighoffer wrote:

>

So if "almost all C compilers" do the same thing, why not just define that thing, and say D does it this way? Why say we depend 100% on C compiler implementation whims? If the corner cases are problematic, ban the corner cases?

Walter already replied to my identical suggestion:
https://forum.dlang.org/post/usnh0c$2180$1@digitalmars.com

March 25

On Thursday, 7 March 2024 at 04:26:56 UTC, Walter Bright wrote:

>

https://github.com/WalterBright/documents/blob/master/bitfields.md

My list of wishes:

  1. bitfields imported from C should use extern(C), this way they can use whatever layout C compiler uses.
  2. D bitfields should be extern(D), and work like bitfields mixin.
  3. Allow specifying default value.

Here is how C3 language does bitfields: https://c3lang.github.io/c3docs/types/#bitstructs
It has guaranteed layout, allows specifying endinanness, optional overlaping of fields. It allows static arrays to be used as a backing type. Its bitfields are done trough a special kind of struct - bitstruct.

April 02
On Thursday, 7 March 2024 at 04:26:56 UTC, Walter Bright wrote:
> https://github.com/WalterBright/documents/blob/master/bitfields.md

I don't know if already mentioned. It's "workaround aura" not "workaround aurora" in ImportC paragraph of the rationale. Aurora means dawn.
April 21
On 3/16/2024 2:40 PM, Timon Gehr wrote:
> In general, how to introspect on bitfields?

Currently, allMembers will get you the name of the bitfield, and you can use .offsetof and .alignof on it. The number of bits can be derived from the .max property. You'll know it's a bitfield if the .max property is less than the type.max.

From those, the bit offsets can be determined, but one could reasonably ask for an easier way to get that.
April 22
On 3/22/2024 7:32 PM, Steven Schveighoffer wrote:
> So if "almost all C compilers" do the same thing, why not just define that thing, and say D does it this way? Why say we depend 100% on C compiler implementation whims? If the corner cases are problematic, ban the corner cases?

I don't see an actual use case for our own layout. They may indeed be whims on the part of the C compiler, but we deliberately pick which C compiler is the "associated C compiler", and why pick a nutburger compiler?

> Pick the "right way", define it,

There isn't a right way.

> and say "This works for most cases in all the C compilers we use, and if it doesn't, you have to figure it out yourself". I don't understand the problem with that. ImportC bitfields *don't have to be the same*. As you once told me, bitfields are not generally used for public API, because of the complications. So why do we need C compatibility in the first place?

One of the uses of bitfields in D is interoperation with C code. It's not unreasonable to have a program that is half in D and half in C. Having different bitfield layouts would just be an aggravation. It would be surprising.


> C does some really dumb things (hindsight, etc.), and D didn't copy all those dumb things. We should continue to not do dumb things.

We copy the dumb way C passes arguments to functions, too. Why? Because it's convenient, easy to explain, nobody questions it, etc. D in the past had a slightly better way of calling C code, and we abandoned that because the nuisance of being different simply was not worth it. Changing it to match C made the problems and the endless effort explaining the difference just go away.

The value of "it is the same as C" is quite large.


> There are other things that aren't specified in the proposal, such as the properties that work on other basic types: `sizeof`, `offsetof`, `alignof`.

ok

April 22
On 3/25/2024 9:39 AM, MrSmith wrote:
> My list of wishes:
> 1. bitfields imported from C should use `extern(C)`, this way they can use whatever layout C compiler uses.
> 2. D bitfields should be `extern(D)`, and work like `bitfields` mixin.
> 3. Allow specifying default value.
> 
> Here is how C3 language does bitfields: https://c3lang.github.io/c3docs/types/#bitstructs
> It has guaranteed layout, allows specifying endinanness, optional overlaping of fields. It allows static arrays to be used as a backing type. Its bitfields are done trough a special kind of struct - `bitstruct`.

Thank you for the link to C3. I read it. Some problems are simply not worth solving, and C3 goes too far.

You can get a consistent layout by simply declaring your bitfields as 'int'. I know this is not specified anywhere, but it works.
April 22
On 3/16/2024 2:32 PM, Timon Gehr wrote:
> On 3/7/24 20:42, Walter Bright wrote:
>> If you are still concerned about the layout, like you want a portable file format, don't use bit fields. Use std.bitmanip.
> 
> Well, that's kind of a foot gun. Portable by default is better.

One thing about language design - there is no rule that overrides every other rule. This applies to everything. Every design is a balance of competing interests.
April 22
Thank you for your thoughts on this. I've thought a lot about it, too!

In the very rare case of actually needing an exact layout, with 5 minutes of effort any layout can be duplicated with C bit fields. If that's too much effort, one can write explicit shift/mask code, and encapsulate it into a function. (Once the function is inlined, there is zero extra overhead for it.) Or one can use std.bitmanip to do that automatically.

Yes, we can add extra syntax and semantics to make this controllable by the user, but it's so rarely needed it's over-engineering.

The preceding is true if one wants a specific layout.

But to algorithmically match what the associated C compiler does, that is more of a significant problem. It took me a while (with the help of Iain) to reverse-engineer it. This is a problem worth solving, and our implementation does solve it. For the user, it effortlessly resolves the issue of binary interoperability with C code.

Good language design means building things into the core language that are the most common use cases, and provide facilities for the uncommon cases. This is why slices are builtin, rather than done with metaprogramming.

An earlier version of D had complex numbers builtin. This did have some advantages over `struct Complex`. But Andrei told me it wasn't worth it. I eventually agreed with him, and took it out. But, for legacy compatibility, that had a very long deprecation period.

Let's spend our limited complexity budget on problems that need to be solved, and explicit bitfield layout isn't one of them.