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. > 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. > > * Say that bit-fields are assigned such types. > > Does behavior change for bit-fields that are standard conforming or > only for implementation defined bit-fields of long. I don't believe anything is abservable for int and unsigned int (or _Bool) bit-fields about the types chosen, beyond the promotions and questions of whether certain out-of-range floating point to bit-field conversions are defined. (There are however testcases in the GCC testsuite for e.g. diagnostics of out-of-range initializers that get implicitly converted to the bit-field type, such as storing 1 in a signed int : 1 bit-field that can only hold 0 and -1.) > > * 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. C requests this via a langhook (which C++ doesn't use). So for > C++ we for example miscompile C++ probably should not have started using these types without also using the langhook. (There may also be bugs in expand where the langhook is inadequate, and of course we should aim for the semantics of GIMPLE to be defined without needing such a langhook.) As a general principle, very little before the RTL stages should care about machine modes; code that cares about them may be using them as a proxy for precision that goes wrong in the presence of bit-field types, and in any case they seem like the wrong level of abstraction for the earlier stages of the compiler. At expand stage at the latest, the full set of types (possibly including bit-field types such as long:33, or Ada types with unusual ranges, or other such constructs) then needs to be mapped onto the lower level machine modes of RTL (at which point many operations also lose the signed/unsigned distinction). Whether this is done at expand, at gimplification or somewhere inbetween may depend on whether we think the tree optimizers can usefully optimize arithmetic on special types before lowering, or whether they should be optimizing arithmetic after lowering (with extra shift/mask operations inserted), or both. -- Joseph S. Myers [EMAIL PROTECTED]