* bitfields treatment
@ 2009-03-20 21:37 Al Viro
2009-03-21 21:57 ` Derek M Jones
0 siblings, 1 reply; 3+ messages in thread
From: Al Viro @ 2009-03-20 21:37 UTC (permalink / raw)
To: linux-sparse
Aside of corner cases associated with signedness, there's another
fun pile we are handling strangely. Namely, treatment of integer promotions
and conversions.
What standard says:
* there's a well-defined behaviour for bitfields based on _Bool, signed int
and unsigned int (int-based is equivalent to one signed or unsigned). We
get it right, AFAICS, and so does gcc.
* implementation can do bitfields based on other types. Fair enough. Both
sparse and gcc allow those for any integer types.
* standard wording is such that it does *NOT* have integer promotions applied
to such bitfields, even if the size is smaller than int. Arguably, that's
a hole in standard; in any case, both gcc and sparse *do* integer promotions
on those, with the same behaviour as usual (value-preserving promotion).
* for all bitfields we are told that they act as (signed or unsigned)
integer types of specified width. That has interesting implications:
unsigned long long f(unsigned long long n)
{
struct {
unsigned long long n:33;
} x = {n};
return x.n + x.n;
}
*must* be equivalent to (n + n) & 0x1ffffffff on all implementations that
allow such bitfields. I.e. these suckers are not promoted to base type;
they act as if we really head 33bit unsigned type, usual conversions in
x.n + x.n left the result with that type and addition had been done within
that type.
gcc does it that way, we do not (x.n gets promoted to unsigned long long).
AFAICS, sparse is wrong here; nothing to do about that, C99 is really not
ambiguous in that area. HOWEVER, that's not the end of story. It's nice
to say "it's an integer type of this width"; however, it is really not enough.
What happens when we mix two such suckers with the same width?
I.e. what about their ranks? gcc seems to do the following: when the width
is equal to that of base type, treat the bitfield as equivalent to the
base type. When the size is smaller, treat all bitfields with this width
and this signedness as belonging to the same type. It leaves a corner case,
though - what if the width *is* equal to that of a smaller normal type?
It *is* possible even on amd64 - there's a 128bit integer type (can't get
to it for bitfield without typedef due to cretinous syntax, but
typedef unsigned __attribute__((mode(TI))) T;
....
T x : 64;
will get it for you). Apparently, that gets treated as equivalent of
the lowest-rank standard type with that size, i.e. unsigned long in case
of amd64. Fsck knows how stable that assumption would be... For now, it
seems that they are careful of having such types only with the widths that
do not overlap with those of standard types and having only one signed/unsigned
pair for given size.
BTW, with typeof() we *can* get to some of those types. We can't apply
typeof to bitfield, but we can say
struct {unsigned long long x:33;} x;
typedef typeof(+x.x) __u33;
and it will actually work as expected with gcc. Can do pointers to them,
etc. Can't get smaller-than-int ones, but that's not particulary interesting
due to integer promotions. I really wonder how well would sparse cope with
that (allocation size > bit_size rounded to byte).
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: bitfields treatment
2009-03-20 21:37 bitfields treatment Al Viro
@ 2009-03-21 21:57 ` Derek M Jones
2009-03-21 23:12 ` Al Viro
0 siblings, 1 reply; 3+ messages in thread
From: Derek M Jones @ 2009-03-21 21:57 UTC (permalink / raw)
To: Al Viro; +Cc: linux-sparse
Al,
> * standard wording is such that it does *NOT* have integer promotions applied
> to such bitfields, even if the size is smaller than int. Arguably, that's
> a hole in standard; in any case, both gcc and sparse *do* integer promotions
> on those, with the same behaviour as usual (value-preserving promotion).
The usual arithmetic conversions (of which integer promotion is a
subset) are performed where the standard says they are performed,
bit-field involving an implementation defined type or not.
> * for all bitfields we are told that they act as (signed or unsigned)
> integer types of specified width. That has interesting implications:
See:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_315.htm
> unsigned long long f(unsigned long long n)
> {
> struct {
> unsigned long long n:33;
> } x = {n};
> return x.n + x.n;
> }
>
> *must* be equivalent to (n + n) & 0x1ffffffff on all implementations that
> allow such bitfields. I.e. these suckers are not promoted to base type;
Sentence 1162 says otherwise:
http://c0x.coding-guidelines.com/6.5.6.html
> they act as if we really head 33bit unsigned type, usual conversions in
> x.n + x.n left the result with that type and addition had been done within
> that type.
>
> gcc does it that way, we do not (x.n gets promoted to unsigned long long).
It has been argued at WG14 that gcc gets it wrong.
> What happens when we mix two such suckers with the same width?
At the very least sparse should generate a useful message.
--
Derek M. Jones tel: +44 (0) 1252 520 667
Knowledge Software Ltd mailto:derek@knosof.co.uk
Source code analysis http://www.knosof.co.uk
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: bitfields treatment
2009-03-21 21:57 ` Derek M Jones
@ 2009-03-21 23:12 ` Al Viro
0 siblings, 0 replies; 3+ messages in thread
From: Al Viro @ 2009-03-21 23:12 UTC (permalink / raw)
To: Derek M Jones; +Cc: linux-sparse
On Sat, Mar 21, 2009 at 09:57:41PM +0000, Derek M Jones wrote:
>> to such bitfields, even if the size is smaller than int. Arguably, that's
>> a hole in standard; in any case, both gcc and sparse *do* integer promotions
>> on those, with the same behaviour as usual (value-preserving promotion).
>
> The usual arithmetic conversions (of which integer promotion is a
> subset) are performed where the standard says they are performed,
> bit-field involving an implementation defined type or not.
The issue is whether integer promotion *do* anything for a type or happen
to be a no-op. 6.3.1.1p2 lists only the bitfields based on _Bool, int,
signed int and unsigned int, leaving the based on "some other implemention-
defined type" case mentioned in 6.7.2.1p4 not covered. Then it proceeds
to say that everything not included in the lists is not affected by
integer promotions.
I.e. 6.3.1.1p2 as written says that e.g.
unsigned long x : 2;
on implementations allowing unsigned long-based bitfields is not affected
by integer promotions. All I can say is that in this case such reading
of standard can get stuffed. The sane behaviour is close to TC proposed
in DR315, except that we should convert *all* bitfields that could be
represented by int/unsigned int resp. If we end up with that in standard -
great, if not... I'm quite willing to go for deliberate non-compliance in
this particular case.
>> * for all bitfields we are told that they act as (signed or unsigned)
>> integer types of specified width. That has interesting implications:
>
> See:
> http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_315.htm
Seen it... AFAICS, the most recent part boils down to "since it's
implementation-defined per 6.7.2.1p4, it's up to implementation to
make up the rules". Not particulary inspiring and Q2 there is a
non-issue. The interesting part is not sizeof, it's modulo by which
the arithmetics is done...
>> unsigned long long f(unsigned long long n)
>> {
>> struct {
>> unsigned long long n:33;
>> } x = {n};
>> return x.n + x.n;
>> }
>>
>> *must* be equivalent to (n + n) & 0x1ffffffff on all implementations that
>> allow such bitfields. I.e. these suckers are not promoted to base type;
>
> Sentence 1162 says otherwise:
> http://c0x.coding-guidelines.com/6.5.6.html
And? Of course usual arithmetic conversions are applied. Integer promotions
leave both arguments unaffected[1], left and right arguments have the same
type, so we get the same type as the result.
If you want to argue that type of either argument is simply unsigned long long,
you'll need more relevant references than that. In particular, I'd like to
see how you propose to explain away 1407: "A bit-field is interpreted as a
signed or unsigned integer type consisting of the specified number of bits."
Unless you are talking about a target where the width of unsigned long long
is 33 bits, I'd say that whatever it is, it's not unsigned long long.
[1] they'd better - neither int nor unsigned int has to be wide enough to
hold the possible value.
>> they act as if we really head 33bit unsigned type, usual conversions in
>> x.n + x.n left the result with that type and addition had been done within
>> that type.
>>
>> gcc does it that way, we do not (x.n gets promoted to unsigned long long).
>
> It has been argued at WG14 that gcc gets it wrong.
What was the outcome of that argument?
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2009-03-21 23:12 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-03-20 21:37 bitfields treatment Al Viro
2009-03-21 21:57 ` Derek M Jones
2009-03-21 23:12 ` Al Viro
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).