SPRAC71B February 2019 – October 2023
The C28x EABI adopts its bit field layout from the IA64 C++ ABI. The following description is consistent with that standard unless explicitly indicated.
The declared type of a bit field is the type that appears in the source code. To hold the value of a bit field, the C and C++ standards allow an implementation to allocate any addressable storage unit large enough to hold it, which need not be related to the declared type. The addressable storage unit is commonly called the container type, and that is how we refer to it in this document. The container type is the major determinant of how bit fields are packed and aligned.
For efficiency, the compiler may access a bit-field with a type that does not match either the declared type or the container type. The declared type and container type are strictly used to determine bit field packing and alignment. The type used to actually load the bit-field is the access type. It can be a narrower type, computed from the size and offset of the bit-field. For instance, in the following example, the container type is 32 bits, but the bit-field will be loaded using a 16-bit access:
struct S
{
long :16;
long bf:16;
};
The C89, C99, and C++ language standards have different requirements for the declared type:
C89 | int, unsigned int, signed int |
C99 | int, unsigned int, signed int, _Bool, or "some other implementation-defined type" |
C++ | Any integral or enumeration type, including bool |
There is no long long type in strict C++, but because C99 has it, C++ compilers commonly support it as an extension. The C99 standard does not require an implementation to support long or long long declared types for bit fields, but because C++ allows it, it is not uncommon for C compilers to support them as well.
A bit field's value is fully contained within its container, exclusive of any padding bits. Containers are properly aligned for their type. The alignment of the structure containing the field is affected by that of the container in the same way as a member object of that type. This also applies to unnamed fields, which is a difference from the IA64 C++ ABI. The container may contain other fields or objects, and may overlap with other containers, but the bits reserved for any one field, including padding for oversized fields, never overlap with those of another field.
In the C28x EABI, the container type of a bit field is its declared type, with one exception. C++ allows so-called oversized bit fields, which have a declared size larger than the declared type. In this case the container is the largest integral type not larger than the declared size of the field.
The layout algorithm maintains a next available bit that is the starting point for allocating a bit field. The steps in the layout algorithm are:
In little-endian mode, containers are filled from LSB to MSB. The C28x uses little-endian mode only.
Zero-length bit fields force the alignment of the following member of a structure to the next alignment boundary corresponding to the declared type, and affect structure alignment.
A declared type of plain int is treated as a signed int by C28x EABI.