Jump to page: 1 26  
Page
Thread overview
March 06
https://github.com/WalterBright/documents/blob/master/bitfields.md
March 07
"gdc/lcd are lumped together because they produce identical results on the same platform."

s/lcd/ldc/

No mention of alignment, total size or the offset.

Needs to mention atomics as not being supported.

No trait to detect a bit field (if its an alias, or by name), nor get its size. Kinda required, enough other things in the language can appear via an alias sequence or by allMembers that are not able to be taken as a pointer of.

The ability to take an alias via getMember needs to be considered if its valid to do so.

No mention of tupleof either, what happens there?

No motivation for not including a D layout for it, instead of forcing everyone into an unpredictable layout that the system C compiler might be using. Moving us off the library type and into a language defined one that is predictable is quite attractive so there needs to be an argument against this.

Also both the post and its subject do not match the guidelines for this forum. So I'm half wondering if it's even worth writing this post knowing that Mike could delete it.

https://github.com/dlang/DIPs/blob/master/docs/guidelines-forums.md#dip-development
March 07

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

>

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

Have you ever thought of the idea of using bit specific integers?

I once saw this one suggestion on the IRC channel: alias i1 = __traits(integer, signed: false, 1);

alias u1 = __traits(integer, true, 1);
alias u3 = __traits(integer, true, 3);
alias u5 = __traits(integer, true, 5);
align(1) struct S
{
    u1 isnothrow;        // nothrow
    u1 isnogc;           // is @nogc
    u1 isproperty;       // can be called without parentheses
    u1 isref;            // returns a reference
    u1 isreturn;         // 'this' is returned by ref
    u1 isscope;          // 'this' is scope
    u1 isreturninferred; // 'this' is return from inference
    u1 isscopeinferred;  // 'this' is scope from inference
    u1 islive;           // is @live
    u1 incomplete;       // return type or default arguments removed
    u1 inoutParam;       // inout on the parameters
    u1 inoutQual;        // inout on the qualifier
    u5 a;
    u3 flags;
}
March 07

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

>

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

>

I've seen plentiful use of it, and have not seen any "do not use bitfields" programming guidelines.

Bit-fields in C have acquired a poor reputation in the programming community

C bitfields considered harmful

So don't go for bitfields "just because"

Bitfields seem to be perfect for this, but they're so poorly specified in the standard that common "best practice" is to avoid them.

March 07

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

>

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

>

The usual way to do bitfields is (culled from the DMD compiler source):

struct S
{
    enum Flags : uint
    {
        isnothrow       = 0x0001, // nothrow
        isnogc          = 0x0002, // is @nogc
        isproperty      = 0x0004, // can be called without parentheses
        isref           = 0x0008, // returns a reference
        isreturn        = 0x0010, // 'this' is returned by ref
        isscope         = 0x0020, // 'this' is scope
        isreturninferred= 0x0040, // 'this' is return from inference
        isscopeinferred = 0x0080, // 'this' is scope from inference
        islive          = 0x0100, // is @live
        incomplete      = 0x0200, // return type or default arguments removed
        inoutParam      = 0x0400, // inout on the parameters
        inoutQual       = 0x0800, // inout on the qualifier
    }

    Flags flags;
}

Granted that this way is pretty common, but it's far from optimal. std.bitmanip.bitfields does this a lot better, even more so when you have multiple-bit fields. Yes, as the DIP says it lacks C compatibility guarantees, but so does this solution. This example is thus a bit of a straw man. Please just supply an example with a standard library bitfield.

In the general use case, portability trumps C compatibility. Therefore, we should and will use std.bitmanip bitfields when we don't explicitly have to be C compatible. What the DIP is suggesting should be considered a special bitfield type, not the "normal" case.

I do not think any syntactic additions to the language itself are a good idea. We don't have any special syntax for normal bitfields either so it would be strange for C-compatible bitfields to have that. It'd be better that C bitfields would be declared with a mixin somewhere in DRuntime, its usage syntax preferably as close as possible to std.bitmanip.bitfields. The compiler can still recognise the call of the mixin as special, but from user POV it should be no different from any other mixin.

March 07
On 3/7/2024 4:04 AM, Dennis wrote:
> On Thursday, 7 March 2024 at 04:26:56 UTC, Walter Bright wrote:
>> https://github.com/WalterBright/documents/blob/master/bitfields.md
> 
>> I've seen plentiful use of it, and have not seen any "do not use bitfields" programming guidelines.
> 
> [Bit-fields in C have acquired a poor reputation in the programming community](https://andrewkelley.me/post/a-better-way-to-implement-bit-fields.html)

All Zig is doing is providing a slightly different syntax that does the same thing as C. Zig is layering on a magic "pointer to bit field type" that I attempted to implement in D long ago, but it has too many special cases and turned out to be unworkable. You cannot convert a pointer to bit 3 to a void*, making the special bit pointer type rather useless.


> [C bitfields considered harmful](https://www.flamingspork.com/blog/2014/11/14/c-bitfields-considered-harmful/)

I don't know of any C compiler that puts a single bit flag in a 64 bit int. He didn't show enough code to see the source of his problem. I suspect he doesn't know what he's doing.


> [So don't go for bitfields "just because"](https://yarchive.net/comp/linux/bitfields.html)

Linus suggests using explicit bit masks instead.


> [Bitfields seem to be perfect for this, but they're so poorly specified in the standard that common "best practice" is to avoid them.](https://www.reddit.com/r/C_Programming/comments/146tbnp/why_is_using_bitfields_in_high_performance/)

I.e. the layout is implementation-defined. That's correct. But in reality, it is fixed. There is no way that gcc on Linux is *ever* going to change the bit field layout, because it would break legions of existing code. It is cast in concrete, and is as immutable as it gets. The same for Microsoft C.

Furthermore, if you use `int` as the base type for bit fields, the layouts are all the same in all the C compilers I've encountered. For practical purposes, it is defined.

If you are still concerned about the layout, like you want a portable file format, don't use bit fields. Use std.bitmanip.

But if you want to be compatible with C code that uses bit fields, the builtin bit fields are the way to go.

If you like a nice syntax, bit fields cannot be beat.

If you want to pack data in your structs and use less memory for your program, bit fields are again a winner. DMD uses far too much memory. Much of the data structs it uses can be packed, but since without bit fields the syntax is just too ugly, there's been little effort to do that. Convenience is everything.

If you still don't like bit fields, don't use them.

And yes, you can't do volatile, shared, atomic, or pointers to bit fields. You can't do those with std.bitmanip, either. Nor can you do them with manual masking and shifting.
March 07

On Thursday, 7 March 2024 at 19:42:36 UTC, Walter Bright wrote:

>

...

You can disagree, but 'I have not seen any "do not use bitfields" programming guidelines' (which wasn't a strong argument to begin with) is now false, so I suggest you replace it in the DIP.

March 07

On Thursday, 7 March 2024 at 19:42:36 UTC, Walter Bright wrote:

>

If you like a nice syntax, bit fields cannot be beat.

There's no need to argue that native bit fields look nicer than manual bit shifts. Of course they do.

>

And yes, you can't do volatile, shared, atomic, or pointers to bit fields.

Of course you can't. No need to defend this.

The main question is: Why inherit C's controversial inconsistent layout scheme? The DIP keeps going on about C interoperability, but only cites abstract "experience" as an argument.

My last use of bit fields was from optimizing std.uni tables: https://github.com/dlang/phobos/pull/8880
Wouldn't it be nice if I could use the shiny new bit fields feature for that? Well I can't: the table needs to know the bit offsets, which would be target dependent. I'd have to use the inferior std.bitmanip. If I didn't know about the platform dependence, I'd use bit fields incorrectly. It would all work until compiling to a different target results in a corrupted table, without warning. After debugging and finding the cause I'd write a blog post "D bit fields considered harmful" like C users have done before.

Why bow down to C and treat D as a second class citizen? The DIP should really substantiate this alleged importance of C-compatibility of non-ImportC D bitfields: Can you name at least one dub package that would benefit from bit fields with C-compatible layout?

March 07
On Thursday, March 7, 2024 3:28:34 PM MST Dennis via dip.development wrote:
> Why bow down to C and treat D as a second class citizen? The DIP should really substantiate this alleged importance of C-compatibility of non-ImportC D bitfields: Can you name at least one dub package that would benefit from bit fields with C-compatible layout?

Having the ability to declare C-compatible bitfields would definitely be useful for binding some C symbols. I was recently dealing with some symbols on Windows where I basically had to skip the bitfields when writing the bindings, because I don't know of any way to bind to them in D.

That being said, I see no reason for bitfields for actual D code to be C-compatible. Unless I'm actually binding to a C type, C-compatibility is irrelevant, and if what C is doing isn't portable, then why would I want it for my D code?

- Jonathan M Davis



March 07
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.

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.
« First   ‹ Prev
1 2 3 4 5 6