The change "[CodeView] Implement support for bit fields in
Clang" (r274201, https://reviews.llvm.org/rL274201) broke the
calculation of bit offsets for the debug info describing bitfields on
big-endian targets.
Prior to commit r274201 the debug info for bitfields got their offsets
from the ASTRecordLayout in CGDebugInfo::CollectRecordFields(), the
current field offset was then passed on to
CGDebugInfo::CollectRecordNormalField() and used directly in the
DIDerivedType.
Since commit r274201, the bit offset ending up in the DIDerivedType no
longer comes directly from the ASTRecordLayout. Instead
CGDebugInfo::CollectRecordNormalField() calls the new method
CGDebugInfo::createBitFieldType(), which in turn calls
CodeGenTypes::getCGRecordLayout().getBitFieldInfo() to fetch a
CGBitFieldInfo describing the field. The 'Offset' member of
CGBitFieldInfo is then used to calculate the bit offset of the
DIDerivedType. Unfortunately the previous and current method of
calculating the bit offset are only equivalent for little endian
targets, as CGRecordLowering::setBitFieldInfo() reverses the bit
offsets for big endian targets as the last thing it does.
A simple reproducer for this error is the following module:
struct fields {
unsigned a : 4; unsigned b : 4;
} flags = {0x0f, 0x1};
Compiled for Mips, with commit r274200 both the DIDerivedType bit
offsets on the IR-level and the DWARF information on the ELF-level
will have the expected values: the offsets of 'a' and 'b' are 0 and 4
respectively. With r274201 the offsets are switched to 4 and 0. By
noting that the static initialization of 'flags' in both cases is the
same, we can eliminate a change in record layout as the cause of the
change in the debug info. Also compiling this example with gcc,
produces the same record layout and debug info as commit r274200.
In order to restore the previous function we extend
CGDebugInfo::createBitFieldType() to compensate for the reversal done
in CGRecordLowering::setBitFieldInfo().