With ms_struct attribut, Zero-length bitfields following

non-bitfield members are ignore. // rdar://8823265 wip

llvm-svn: 130257
This commit is contained in:
Fariborz Jahanian 2011-04-26 23:52:16 +00:00
parent 79ea878bf9
commit bcb23a180b
3 changed files with 184 additions and 6 deletions

View File

@ -564,6 +564,8 @@ protected:
unsigned IsUnion : 1;
unsigned IsMac68kAlign : 1;
unsigned IsMsStruct : 1;
/// UnfilledBitsInLastByte - If the last field laid out was a bitfield,
/// this contains the number of bits in the last byte that can be used for
@ -612,7 +614,8 @@ protected:
*EmptySubobjects)
: Context(Context), EmptySubobjects(EmptySubobjects), Size(0),
Alignment(CharUnits::One()), UnpackedAlignment(Alignment),
Packed(false), IsUnion(false), IsMac68kAlign(false),
Packed(false), IsUnion(false),
IsMac68kAlign(false), IsMsStruct(false),
UnfilledBitsInLastByte(0), MaxFieldAlignment(CharUnits::Zero()),
DataSize(0), NonVirtualSize(CharUnits::Zero()),
NonVirtualAlignment(CharUnits::One()), PrimaryBase(0),
@ -1148,6 +1151,8 @@ void RecordLayoutBuilder::InitializeLayout(const Decl *D) {
IsUnion = RD->isUnion();
Packed = D->hasAttr<PackedAttr>();
IsMsStruct = D->hasAttr<MsStructAttr>();
// mac68k alignment supersedes maximum field alignment and attribute aligned,
// and forces all structures to have 2-byte alignment. The IBM docs on it
@ -1249,9 +1254,21 @@ void RecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) {
void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
// Layout each field, for now, just sequentially, respecting alignment. In
// the future, this will need to be tweakable by targets.
const FieldDecl *LastFD = 0;
for (RecordDecl::field_iterator Field = D->field_begin(),
FieldEnd = D->field_end(); Field != FieldEnd; ++Field)
FieldEnd = D->field_end(); Field != FieldEnd; ++Field) {
if (IsMsStruct) {
// Zero-length bitfields following non-bitfield members are
// ignored:
const FieldDecl *FD = (*Field);
if (FD->isBitField() && LastFD && !LastFD->isBitField() &&
FD->getBitWidth()->EvaluateAsInt(Context).getZExtValue() == 0) {
continue;
}
LastFD = FD;
}
LayoutField(*Field);
}
}
void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,

View File

@ -77,6 +77,9 @@ public:
/// Packed - Whether the resulting LLVM struct will be packed or not.
bool Packed;
/// IsMsStruct - Whether ms_struct is in effect or not
bool IsMsStruct;
private:
CodeGenTypes &Types;
@ -184,7 +187,8 @@ public:
CGRecordLayoutBuilder(CodeGenTypes &Types)
: BaseSubobjectType(0),
IsZeroInitializable(true), IsZeroInitializableAsBase(true),
Packed(false), Types(Types), BitsAvailableInLastField(0) { }
Packed(false), IsMsStruct(false),
Types(Types), BitsAvailableInLastField(0) { }
/// Layout - Will layout a RecordDecl.
void Layout(const RecordDecl *D);
@ -195,6 +199,8 @@ public:
void CGRecordLayoutBuilder::Layout(const RecordDecl *D) {
Alignment = Types.getContext().getASTRecordLayout(D).getAlignment();
Packed = D->hasAttr<PackedAttr>();
IsMsStruct = D->hasAttr<MsStructAttr>();
if (D->isUnion()) {
LayoutUnion(D);
@ -739,9 +745,24 @@ bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
LayoutNonVirtualBases(RD, Layout);
unsigned FieldNo = 0;
const FieldDecl *LastFD = 0;
for (RecordDecl::field_iterator Field = D->field_begin(),
FieldEnd = D->field_end(); Field != FieldEnd; ++Field, ++FieldNo) {
if (IsMsStruct) {
// Zero-length bitfields following non-bitfield members are
// ignored:
const FieldDecl *FD = (*Field);
// FIXME. Refactor into common code as it is used in several places.
if (FD->isBitField() && LastFD && !LastFD->isBitField() &&
FD->getBitWidth()->
EvaluateAsInt(Types.getContext()).getZExtValue() == 0) {
--FieldNo;
continue;
}
LastFD = FD;
}
if (!LayoutField(*Field, Layout.getFieldOffset(FieldNo))) {
assert(!Packed &&
"Could not layout fields even with a packed LLVM struct!");
@ -960,6 +981,8 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) {
const ASTRecordLayout &AST_RL = getContext().getASTRecordLayout(D);
RecordDecl::field_iterator it = D->field_begin();
const FieldDecl *LastFD = 0;
bool IsMsStruct = D->hasAttr<MsStructAttr>();
for (unsigned i = 0, e = AST_RL.getFieldCount(); i != e; ++i, ++it) {
const FieldDecl *FD = *it;
@ -969,13 +992,28 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) {
unsigned FieldNo = RL->getLLVMFieldNo(FD);
assert(AST_RL.getFieldOffset(i) == SL->getElementOffsetInBits(FieldNo) &&
"Invalid field offset!");
LastFD = FD;
continue;
}
if (IsMsStruct) {
// Zero-length bitfields following non-bitfield members are
// ignored:
if (FD->isBitField() && LastFD && !LastFD->isBitField() &&
FD->getBitWidth()->
EvaluateAsInt(getContext()).getZExtValue() == 0) {
--i;
continue;
}
LastFD = FD;
}
// Ignore unnamed bit-fields.
if (!FD->getDeclName())
if (!FD->getDeclName()) {
LastFD = FD;
continue;
}
const CGBitFieldInfo &Info = RL->getBitFieldInfo(FD);
for (unsigned i = 0, e = Info.getNumComponents(); i != e; ++i) {
const CGBitFieldInfo::AccessInfo &AI = Info.getComponent(i);

View File

@ -0,0 +1,123 @@
// RUN: %clang_cc1 -emit-llvm-only -triple x86_64-apple-darwin9 %s
// rdar://8823265
#define ATTR __attribute__((__ms_struct__))
struct
{
char foo;
long : 0;
char bar;
} ATTR t1;
struct
{
char foo;
long : 0;
char : 0;
int : 0;
char bar;
} ATTR t2;
struct
{
char foo;
long : 0;
char : 0;
int : 0;
char bar;
long : 0;
char : 0;
} ATTR t3;
struct
{
long : 0;
char bar;
} ATTR t4;
struct
{
long : 0;
long : 0;
char : 0;
char bar;
} ATTR t5;
struct
{
long : 0;
long : 0;
char : 0;
char bar;
} ATTR t6;
struct
{
char foo;
long : 0;
int : 0;
char bar;
char bar1;
long : 0;
char bar2;
char bar3;
char : 0;
char bar4;
char bar5;
char : 0;
char bar6;
char bar7;
} ATTR t7;
struct
{
long : 0;
long : 0;
char : 0;
} ATTR t8;
struct
{
char foo;
long : 0;
int : 0;
char bar;
char bar1;
long : 0;
char bar2;
char bar3;
char : 0;
char bar4;
char bar5;
char : 0;
char bar6;
char bar7;
int i1;
char : 0;
long : 0;
char :4;
char bar8;
char : 0;
char bar9;
char bar10;
int i2;
char : 0;
long : 0;
char :4;
} ATTR t9;
static int arr1[(sizeof(t1) == 2) -1];
static int arr2[(sizeof(t2) == 2) -1];
static int arr3[(sizeof(t3) == 2) -1];
static int arr4[(sizeof(t4) == 1) -1];
static int arr5[(sizeof(t5) == 1) -1];
static int arr6[(sizeof(t6) == 1) -1];
static int arr7[(sizeof(t7) == 9) -1];
static int arr8[(sizeof(t8) == 0) -1];
static int arr9[(sizeof(t9) == 28) -1];
int main() {
return 0;
}