diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2011-04-26 23:52:16 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2011-04-26 23:52:16 +0000 |
commit | 62055b0618fafb4747e783ba3fedd7bc7d57d27d (patch) | |
tree | d2a0950baf9116b777be7e46c8576020a7555bf1 | |
parent | 028ea4bf0c643e0e2a8fa086c28beb0d5b594ba7 (diff) | |
download | clang-62055b0618fafb4747e783ba3fedd7bc7d57d27d.tar.gz |
With ms_struct attribut, Zero-length bitfields following
non-bitfield members are ignore. // rdar://8823265 wip
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130257 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/AST/RecordLayoutBuilder.cpp | 21 | ||||
-rw-r--r-- | lib/CodeGen/CGRecordLayoutBuilder.cpp | 46 | ||||
-rw-r--r-- | test/CodeGen/ms_struct-bitfield.c | 123 |
3 files changed, 184 insertions, 6 deletions
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 75228a2b7b..c4a156fbcc 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -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, diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp index 24caf68d76..d202b6e825 100644 --- a/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -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); diff --git a/test/CodeGen/ms_struct-bitfield.c b/test/CodeGen/ms_struct-bitfield.c new file mode 100644 index 0000000000..e9bd1d3f31 --- /dev/null +++ b/test/CodeGen/ms_struct-bitfield.c @@ -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; +} + |