[Cxx-abi-dev] Overlong bit fields and 128-bit integers

David Vandevoorde daveed at edg.com
Tue Sep 20 13:51:21 UTC 2011


(Re-posting after a couple of weeks due to mailing list transition issues.)

As you can tell from the subject line keywords we're well in "odd corner case" territory here, but we received an ABI compatibility problem report in this area.

Consider:

	struct S {
	  int i;
	  long long x: 130;
	  int j;
	};

What's the offset of j?

Here is what the IA-64 C++ ABI has to say wrt. bit field allocation (2.4.II/1):

> If D is a (possibly unnamed) bitfield whose declared type is T and whose declared width is n bits:
> There are two cases depending on sizeof(T) and n:
> 
> 	• If sizeof(T)*8 >= n, the bitfield is allocated as required by the underlying C psABI, subject to the constraint that a bitfield is never placed in the tail padding of a base class of C.
> If dsize(C) > 0, and the byte at offset dsize(C) - 1 is partially filled by a bitfield, and that bitfield is also a data member declared in C (but not in one of C's proper base classes), the next available bits are the unfilled bits at offset dsize(C) - 1. Otherwise, the next available bits are at offset dsize(C).
> 
> Update align(C) to max (align(C), align(T)).
> 
> 	• If sizeof(T)*8 < n, let T' be the largest integral POD type with sizeof(T')*8 <= n. The bitfield is allocated starting at the next offset aligned appropriately for T', with length n bits. The first sizeof(T)*8 bits are used to hold the value of the bitfield, followed by n - sizeof(T)*8 bits of padding.
> Update align(C) to max (align(C), align(T')).
> 
> In either case, update dsize(C) to include the last byte containing (part of) the bitfield, and update sizeof(C) to max(sizeof(C),dsize(C)).



Here we're dealing with the second bullet because sizeof(long long)*8 < 130 (long long is 8 bytes). We emulate GCC modes that permit 128-bit integral types, and in those modes, T' is __int128, a 16-byte aligned type.  That means that the addition of __int128 has changed the layout of a structure that doesn't involve __int128 at all!

GCC keeps the alignment of the bit field at an 8-byte boundary in this case, and that makes sense to me, but for:

	struct S2 {
	  int i;
	  __int128 x: 130;
	  int j;
	};

it does the same, which does not make sense to me: If I used a __int128 type for the field, I presumably want the associated alignment used.

I'd like to therefore propose changing this such that:

	- for standard C++11 integral types use the existing rule
	- for integral types not defined in C++11, limit T' to the standard C++11 types and the declared bit field container type

What do you all think?

	Daveed



More information about the cxx-abi-dev mailing list