зеркало из https://github.com/microsoft/clang.git
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:
Родитель
81140a5bc2
Коммит
4cf6f5fdc5
|
@ -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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче