More work on wide bit-fields, WIP.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101467 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Anders Carlsson 2010-04-16 15:57:11 +00:00
Родитель 81140a5bc2
Коммит 4cf6f5fdc5
3 изменённых файлов: 85 добавлений и 1 удалений

Просмотреть файл

@ -609,6 +609,66 @@ void ASTRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
LayoutField(*Field);
}
void ASTRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
uint64_t TypeSize) {
assert(Context.getLangOptions().CPlusPlus &&
"Can only have wide bit-fields in C++!");
// Itanium C++ ABI 2.4:
// If sizeof(T)*8 < n, let T' be the largest integral POD type with
// sizeof(T')*8 <= n.
QualType IntegralPODTypes[] = {
Context.UnsignedCharTy, Context.UnsignedShortTy, Context.UnsignedIntTy,
Context.UnsignedLongTy, Context.UnsignedLongLongTy
};
printf("field sizes %llu type size %llu\n",
FieldSize, TypeSize);
QualType Type;
for (unsigned I = 0, E = llvm::array_lengthof(IntegralPODTypes);
I != E; ++I) {
uint64_t Size = Context.getTypeSize(IntegralPODTypes[I]);
printf("going to try %s %llu\n", IntegralPODTypes[I].getAsString().c_str(),
Size);
if (Size > FieldSize)
break;
Type = IntegralPODTypes[I];
}
assert(!Type.isNull() && "Did not find a type!");
printf("type should be %s\n", Type.getAsString().c_str());
unsigned TypeAlign = Context.getTypeAlign(Type);
// We're not going to use any of the unfilled bits in the last byte.
UnfilledBitsInLastByte = 0;
// The bitfield is allocated starting at the next offset aligned appropriately
// for T', with length n bits.
uint64_t FieldOffset = llvm::RoundUpToAlignment(DataSize, TypeAlign);
if (IsUnion) {
DataSize = std::max(DataSize, FieldSize);
} else {
uint64_t NewSizeInBits = FieldOffset + FieldSize;
DataSize = llvm::RoundUpToAlignment(NewSizeInBits, 8);
UnfilledBitsInLastByte = DataSize - NewSizeInBits;
}
// Place this field at the current location.
FieldOffsets.push_back(FieldOffset);
// Update the size.
Size = std::max(Size, DataSize);
// Remember max struct/class alignment.
UpdateAlignment(TypeAlign);
}
void ASTRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
uint64_t FieldOffset = IsUnion ? 0 : (DataSize - UnfilledBitsInLastByte);
@ -618,6 +678,11 @@ void ASTRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
uint64_t TypeSize = FieldInfo.first;
unsigned FieldAlign = FieldInfo.second;
if (FieldSize > TypeSize) {
LayoutWideBitField(FieldSize, TypeSize);
return;
}
if (FieldPacked || !Context.Target.useBitFieldTypeAlignment())
FieldAlign = 1;
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())

Просмотреть файл

@ -91,6 +91,7 @@ class ASTRecordLayoutBuilder {
void LayoutFields(const RecordDecl *D);
void LayoutField(const FieldDecl *D);
void LayoutWideBitField(uint64_t FieldSize, uint64_t TypeSize);
void LayoutBitField(const FieldDecl *D);
/// DeterminePrimaryBase - Determine the primary base of the given class.

Просмотреть файл

@ -3,10 +3,28 @@
#define CHECK_SIZE(name, size) extern int name##1[sizeof(name) == size ? 1 : -1];
#define CHECK_ALIGN(name, size) extern int name##2[__alignof(name) == size ? 1 : -1];
// Simple test.
// Simple tests.
struct Test1 {
char c : 9; // expected-warning {{size of bit-field 'c' (9 bits) exceeds the size of its type; value will be truncated to 8 bits}}
};
CHECK_SIZE(Test1, 2);
CHECK_ALIGN(Test1, 1);
struct Test2 {
char c : 16; // expected-warning {{size of bit-field 'c' (16 bits) exceeds the size of its type; value will be truncated to 8 bits}}
};
CHECK_SIZE(Test2, 2);
CHECK_ALIGN(Test2, 2);
struct Test3 {
char c : 32; // expected-warning {{size of bit-field 'c' (32 bits) exceeds the size of its type; value will be truncated to 8 bits}}
};
CHECK_SIZE(Test3, 4);
CHECK_ALIGN(Test3, 4);
struct Test4 {
char c : 64; // expected-warning {{size of bit-field 'c' (64 bits) exceeds the size of its type; value will be truncated to 8 bits}}
};
CHECK_SIZE(Test4, 8);
CHECK_ALIGN(Test4, 8);