This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Rant and proposal about bitfield semantics in our IL and the C/C++ Frontend
On Tue, 15 Jan 2008, Joseph S. Myers wrote:
> On Mon, 14 Jan 2008, Richard Guenther wrote:
>
> > Can you clarify on the resulting promotions? As I remember the
> > standard defines promotions based on the representable values, so
> > long : 15 gets promoted to int, but long : 33 doesn't get promoted.
> > In the C++ FE at least we promote to the _declared_ type, that is,
> > to long in this case. (Which I find more natural, but may be not
> > what the standard says).
>
> Types (including the bit-field width as part of the type) narrower than
> int are promoted based on representable values (so to int). Types wider
> than int are left unchanged by the promotions.
>
> > Now, if you assign a rank to long : 15 (is it the same as int : 15?),
>
> They are the same; we only provide a single signed and a single unsigned
> bit-field type of each width. (For int : 32, or other cases where the
> width is the full width of the declared type, we used the declared type;
> for cases where the width is that of a narrower standard type, we use that
> narrower standard type, with c_build_bitfield_integer_type determining
> preferences among types of the same width.)
>
> > would it still promote to int or would it promote to long or neither?
>
> To int, because int can represent all the values.
Ok, this is all as expected.
>
> > The question arises when computing the value of say long : 33 i;
> > i << 16 >> 16. Is the shift performed in long : 33 type? Is an
> > out-of-range value truncated?
>
> Performed in long : 33, according to the rules for shifts defined in
> implement-c.texi (which define some cases ISO C leaves
> implementation-defined, and one that's implementation-defined in C90 but
> undefined in C99.)
>
> Arithmetic also follows the usual ISO C rules (e.g. signed overflow
> undefined, subject to -fwrapv making it modulo; unsigned overflow modulo).
> Arithmetic in narrow bit-field types e.g. int:25 won't appear at the
> language level any more than arithmetic in short does, because both get
> promoted to int.
So this would probably not match behavior of other compilers which
seem to do promotion to either the declared type or a non-bitfield
type that can hold all the values of the bitfield. To make the example
defined, consider an unsigned long : 33 i that is initialized to
1ul << 32. The expression i << 1 >> 1 is evaluated to 1ul << 32
by the compilers I have access to (and also by GCC), not zero.
The C++ frontend does in most places promote bitfield operands to
the declared type (if it didn't get promoted by integer promotion
rules before).
> > > * Make the gimplifier (or a later tree-ssa pass) insert whatever
> > > conversions / reductions in precision may be needed to produce trees
> > > acceptable to expand, if you think expand can't handle the special types
> > > reliably. In particular, for arithmetic on such types and on all
> > > conversions to such types. (Without special types, special code is still
> > > needed for assignments to bit-fields, no longer handled as conversions.)
> >
> > (The problem is that I'm trying to exactly define what it should mean
> > to the middle-end to for example do a NOP conversion to a bitfield - this
> > is not at all clear)
>
> The conversions between integer types should I think be defined in GIMPLE
> to follow the same rules as the C language conversions, documented in
> implement-c.texi for cases ISO C leaves implemenation-defined: that is,
> always reducing modulo 2^N to fit within the range of the type (except for
> conversions to _Bool).
Right. The middle-end certainly assumes this will happen (and honors
these conversions) - apart from expand, where such conversions are
either dropped completely (unless they change the mode), or (at least
partly) honored if the REDUCE_BIT_FIELD_OPERATIONS langhook is set
(which it is for C, but not for C++).
Just to state the facts again - I'm back to square one ;)
Thanks,
Richard.