View mode: basic / threaded / horizontal-split · Log in · Help
July 30, 2012
Why must butfields sum to a multiple of a byte?
It says for std.bitmanip.bitfields:

"The sum of all bit lengths in one bitfield instantiation must be
exactly 8, 16, 32, or 64."
It has a static assert to verify this. But why does this limitation exist?

I was thinking of cases where I'm wrapping a C++ POD struct which has
bitfields and is packed on a 1-byte boundary. GCC example:

#include <stdio.h>
#pragma pack(1)
struct Foo
{
   unsigned int bits1 : 1;
   unsigned int bits2 : 2;
};

int main()
{
   printf("%d\n", sizeof(Foo));
   return 0;
}

I can't translate this to D using the bitfields mixin since it
requires a multiple of a byte, 3 bits isn't a byte:

import std.stdio;
import std.bitmanip;

align(1) struct Foo
{
   mixin(bitfields!(
       uint, "bits1", 1,
       uint, "bits2", 2
   ));
}

void main() { writeln(Foo.sizeof); }

std\bitmanip.d(151): Error: static assert  "Field widths must sum to
8, 16, 32, or 64"

Is this a language limitation? I guess because 'byte' is the smallest
legal type in D this is what the bitfields mixin uses internally?
July 30, 2012
Re: Why must butfields sum to a multiple of a byte?
On Monday, 30 July 2012 at 14:19:56 UTC, Andrej Mitrovic wrote:
> It says for std.bitmanip.bitfields:
>
> "The sum of all bit lengths in one bitfield instantiation must 
> be
> exactly 8, 16, 32, or 64."
> It has a static assert to verify this. But why does this 
> limitation exist?
>
> I was thinking of cases where I'm wrapping a C++ POD struct 
> which has
> bitfields and is packed on a 1-byte boundary. GCC example:
>
> #include <stdio.h>
> #pragma pack(1)
> struct Foo
> {
>     unsigned int bits1 : 1;
>     unsigned int bits2 : 2;
> };
>
> int main()
> {
>     printf("%d\n", sizeof(Foo));
>     return 0;
> }
>
> I can't translate this to D using the bitfields mixin since it
> requires a multiple of a byte, 3 bits isn't a byte:
>
> import std.stdio;
> import std.bitmanip;
>
> align(1) struct Foo
> {
>     mixin(bitfields!(
>         uint, "bits1", 1,
>         uint, "bits2", 2
>     ));
> }
>
> void main() { writeln(Foo.sizeof); }
>
> std\bitmanip.d(151): Error: static assert  "Field widths must 
> sum to
> 8, 16, 32, or 64"
>
> Is this a language limitation? I guess because 'byte' is the 
> smallest
> legal type in D this is what the bitfields mixin uses 
> internally?
I think you are supposed to explicitly pad the field yourself:

----
align(1) struct Foo
{
   mixin(bitfields!(
       uint, "bits1", 1,
       uint, "bits2", 2,
       uint, "", 5
   ));
}
----
The rationale (I *think*) Is that bitfields wants to know how big 
it should be: While YOU know you want to put it into a "Foo" 
object that is 1 byte big, bitfields has no idea.

Either that, or having the developer provide this by hand made 
the implementation easier enough to justify the burden?

Even then, I think it would have been more convenient to specify 
the total size as a first argument, rather than manually padding 
at the end.

Either way, nothing world shattering for me :D
July 30, 2012
Re: Why must butfields sum to a multiple of a byte?
On 7/30/12, monarch_dodra <monarchdodra@gmail.com> wrote:
> I think you are supposed to explicitly pad the field yourself:

You're right, I missed that part of the documentation. :)
July 30, 2012
Re: Why must butfields sum to a multiple of a byte?
On 07/30/2012 07:19 AM, Andrej Mitrovic wrote:

> I was thinking of cases where I'm wrapping a C++ POD struct which has
> bitfields and is packed on a 1-byte boundary.

It is inherently unportable because unlike D, bitfields in C and C++ 
give too much freedom to the compiler. The compiler can move the fields 
around at will.

Ali
July 30, 2012
Re: Why must butfields sum to a multiple of a byte?
On 7/30/12, Ali Çehreli <acehreli@yahoo.com> wrote:
> It is inherently unportable because unlike D, bitfields in C and C++
> give too much freedom to the compiler. The compiler can move the fields
> around at will.

I really need to figure out a reliable way to extract this
information, at least for the target platform a library is compiled
on. gccxml gives some information which seems to be somewhat reliable
but according to the authors it's more of a guess than accurate info
(2nd paragraph):
http://www.gccxml.org/pipermail/gccxml/2012-February/001483.html

Still this isn't too shabby, there could be configuration options
where the user could set pack/bitsize/compiler options and similar
stuff which would make a codegenerator more reliable.
July 30, 2012
Re: Why must butfields sum to a multiple of a byte?
On 07/30/2012 09:44 AM, Andrej Mitrovic wrote:
> On 7/30/12, Ali Çehreli<acehreli@yahoo.com>  wrote:
>> It is inherently unportable because unlike D, bitfields in C and C++
>> give too much freedom to the compiler. The compiler can move the fields
>> around at will.
>
> I really need to figure out a reliable way to extract this
> information, at least for the target platform a library is compiled
> on.

The program should be able to detect the placements of the fields. You 
can expect a certain bit pattern for a given set of values of the bit 
fields, set those values, read them on the D side, detect potential 
inconsistencies, and fail the execution (or hopefully compilation).

Ali
July 30, 2012
Re: Why must butfields sum to a multiple of a byte?
On 7/30/12, Ali Çehreli <acehreli@yahoo.com> wrote:
> The program should be able to detect the placements of the fields. You
> can expect a certain bit pattern for a given set of values of the bit
> fields, set those values, read them on the D side, detect potential
> inconsistencies, and fail the execution (or hopefully compilation).

Yeah that was exactly my thinking, these things can be automated
although they might slow down the whole codegeneration process a
little bit (not that it matters much since you would rarely have to
regenerate).

Btw, I get an internal std error with this mixin:

import std.bitmanip;
struct Foo
{
   mixin(bitfields!(
       uint, "bits1", 32,
   ));
}

D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\bitmanip.d(76): Error:
shift by 32 is outside the range 0..31

Should I file this?
July 30, 2012
Re: Why must butfields sum to a multiple of a byte?
On 07/30/2012 10:15 AM, Andrej Mitrovic wrote:

> import std.bitmanip;
> struct Foo
> {
>      mixin(bitfields!(
>          uint, "bits1", 32,
>      ));
> }
>
> D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\bitmanip.d(76): Error:
> shift by 32 is outside the range 0..31
>
> Should I file this?

Yes, it's a bug.

Ali
July 30, 2012
Re: Why must butfields sum to a multiple of a byte?
On Monday, 30 July 2012 at 17:15:54 UTC, Andrej Mitrovic wrote:
> On 7/30/12, Ali Çehreli <acehreli@yahoo.com> wrote:
>> The program should be able to detect the placements of the 
>> fields. You
>> can expect a certain bit pattern for a given set of values of 
>> the bit
>> fields, set those values, read them on the D side, detect 
>> potential
>> inconsistencies, and fail the execution (or hopefully 
>> compilation).
>
> Yeah that was exactly my thinking, these things can be automated
> although they might slow down the whole codegeneration process a
> little bit (not that it matters much since you would rarely 
> have to
> regenerate).
>
> Btw, I get an internal std error with this mixin:
>
> import std.bitmanip;
> struct Foo
> {
>     mixin(bitfields!(
>         uint, "bits1", 32,
>     ));
> }
>
> D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\bitmanip.d(76): 
> Error:
> shift by 32 is outside the range 0..31
>
> Should I file this?

Yes, that should work.

By the way, what's a "butfield"?
July 30, 2012
Re: Why must butfields sum to a multiple of a byte?
On 7/30/12, monarch_dodra <monarchdodra@gmail.com> wrote:
> By the way, what's a "butfield"?

LOL I haven't even noticed.
« First   ‹ Prev
1 2 3 4 5
Top | Discussion index | About this forum | D home