summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/RecordLayoutBuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/RecordLayoutBuilder.cpp')
-rw-r--r--clang/lib/AST/RecordLayoutBuilder.cpp52
1 files changed, 32 insertions, 20 deletions
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp
index df7ed57a580..983a2874a73 100644
--- a/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -297,7 +297,11 @@ class RecordLayoutBuilder {
llvm::SmallVector<uint64_t, 16> FieldOffsets;
/// Packed - Whether the record is packed or not.
- bool Packed;
+ unsigned Packed : 1;
+
+ unsigned IsUnion : 1;
+
+ unsigned IsMac68kAlign : 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
@@ -311,8 +315,6 @@ class RecordLayoutBuilder {
/// DataSize - The data size of the record being laid out.
uint64_t DataSize;
- bool IsUnion;
-
uint64_t NonVirtualSize;
unsigned NonVirtualAlignment;
@@ -350,9 +352,10 @@ class RecordLayoutBuilder {
RecordLayoutBuilder(ASTContext &Context, EmptySubobjectMap *EmptySubobjects)
: Context(Context), EmptySubobjects(EmptySubobjects), Size(0), Alignment(8),
- Packed(false), UnfilledBitsInLastByte(0), MaxFieldAlignment(0), DataSize(0),
- IsUnion(false), NonVirtualSize(0), NonVirtualAlignment(8), PrimaryBase(0),
- PrimaryBaseIsVirtual(false), FirstNearlyEmptyVBase(0) { }
+ Packed(false), IsUnion(false), IsMac68kAlign(false),
+ UnfilledBitsInLastByte(0), MaxFieldAlignment(0), DataSize(0),
+ NonVirtualSize(0), NonVirtualAlignment(8), PrimaryBase(0),
+ PrimaryBaseIsVirtual(false), FirstNearlyEmptyVBase(0) { }
void Layout(const RecordDecl *D);
void Layout(const CXXRecordDecl *D);
@@ -423,7 +426,7 @@ class RecordLayoutBuilder {
void UpdateEmptyClassOffsets(const FieldDecl *FD, uint64_t Offset);
/// InitializeLayout - Initialize record layout for the given record decl.
- void InitializeLayout(const RecordDecl *D);
+ void InitializeLayout(const Decl *D);
/// FinishLayout - Finalize record layout. Adjust record size based on the
/// alignment.
@@ -942,16 +945,27 @@ RecordLayoutBuilder::UpdateEmptyClassOffsets(const FieldDecl *FD,
}
}
-void RecordLayoutBuilder::InitializeLayout(const RecordDecl *D) {
- IsUnion = D->isUnion();
+void RecordLayoutBuilder::InitializeLayout(const Decl *D) {
+ if (const RecordDecl *RD = dyn_cast<RecordDecl>(D))
+ IsUnion = RD->isUnion();
Packed = D->hasAttr<PackedAttr>();
- if (const MaxFieldAlignmentAttr *MFAA = D->getAttr<MaxFieldAlignmentAttr>())
- MaxFieldAlignment = MFAA->getAlignment();
+ // mac68k alignment supersedes maximum field alignment and attribute aligned,
+ // and forces all structures to have 2-byte alignment. The IBM docs on it
+ // allude to additional (more complicated) semantics, especially with regard
+ // to bit-fields, but gcc appears not to follow that.
+ if (D->hasAttr<AlignMac68kAttr>()) {
+ IsMac68kAlign = true;
+ MaxFieldAlignment = 2 * 8;
+ Alignment = 2 * 8;
+ } else {
+ if (const MaxFieldAlignmentAttr *MFAA = D->getAttr<MaxFieldAlignmentAttr>())
+ MaxFieldAlignment = MFAA->getAlignment();
- if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
- UpdateAlignment(AA->getMaxAlignment());
+ if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
+ UpdateAlignment(AA->getMaxAlignment());
+ }
}
void RecordLayoutBuilder::Layout(const RecordDecl *D) {
@@ -1020,13 +1034,7 @@ void RecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) {
DataSize = Size;
}
- Packed = D->hasAttr<PackedAttr>();
-
- if (const MaxFieldAlignmentAttr *MFAA = D->getAttr<MaxFieldAlignmentAttr>())
- MaxFieldAlignment = MFAA->getAlignment();
-
- if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
- UpdateAlignment(AA->getMaxAlignment());
+ InitializeLayout(D);
// Layout each ivar sequentially.
llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
@@ -1239,6 +1247,10 @@ void RecordLayoutBuilder::FinishLayout() {
}
void RecordLayoutBuilder::UpdateAlignment(unsigned NewAlignment) {
+ // The alignment is not modified when using 'mac68k' alignment.
+ if (IsMac68kAlign)
+ return;
+
if (NewAlignment <= Alignment)
return;
OpenPOWER on IntegriCloud