This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Folding a bitfield in a union

Greetings everybody,

I'm seeking your advice on how to best solve a bug. The issue has to do with folding a bitfield contained in a union. Consider the following example:

union U {
  unsigned int a:24;
  unsigned int b:20;
} u = { .a = 0x345678 };

int foo (void)
  return u.b;

Currently, folding (fold_nonarray_ctor_reference and fold_ctor_reference)
does the following:

1) Compute the difference between bit offset of a and b
2) Check that b's area is within a's area in memory
3) Do nothing if 1) yields a non-zero difference
4) Cast value stored in a according to the size of b by removing bits of
highest weight (via VIEW_CONVERT_EXPR).

This does not work for big endian targets since bitfield respect byte
endianness (and I support word endianness) when layed out in memory.
So a would end up like this (highest addresses on the right):

|  Ox34 | 0x56 | 0x78 |

b would be the first two byte and then 4 highest bits of the third byte,
as if memory was a sequence of bits instead bytes with highest value
bits at the lowest "bit address"

So the expected result would be 0x34567 but a cast as does
VIEW_CONVERT_EXPR would return 0x45678. Forbidding folding in such
case for big endian would work but I've been looking about a way to
make bitfield folding also work for big endian. The approach I've been
taking so far is to enhance native_encode_integer and
native_interpret_integer to take a start parameter and express start
and len as addressing bits rather than byte. Then in
fold_nonarray_ctor_reference whenever the constructor is for a
bitfield, that bitfield is encoded with its bit offset and bit length to
target memory layout, then interpreted to the host as its type qualifier
(unsigned int in the above example). Finally, a call to fold_ternary with
a subcode of BIT_FIELD_REF is made which will encode that integer to
the target memory layout as the type qualifier and decode it according
to the bit offset and bit length of bitfield b. Note that juste replacing
VIEW_CONVERT_EXPR by BIT_FIELD_REF has the advantage of
allowing folding in simpler solutions like a union of an integer and
a char which is currently not folded even for little endian target.

However this double conversion between host and target memory
layout is unelegant and unefficient. I could do just one conversion
completely in fold_nonarray_ctor_reference but somehow I feel it is
not the right place to do it. As anybody a better advice?

Best regards,

Thomas Preud'homme

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]