summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGRecordLayoutBuilder.cpp20
-rw-r--r--clang/lib/CodeGen/CGRecordLayoutBuilder.h5
2 files changed, 23 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
index d3699bb992d..4576b808f02 100644
--- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -27,13 +27,15 @@ using namespace clang;
using namespace CodeGen;
void CGRecordLayoutBuilder::Layout(const RecordDecl *D) {
+ Alignment = Types.getContext().getASTRecordLayout(D).getAlignment() / 8;
+
if (D->isUnion()) {
LayoutUnion(D);
return;
}
Packed = D->hasAttr<PackedAttr>();
-
+
if (LayoutFields(D))
return;
@@ -115,6 +117,21 @@ bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D,
const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(D->getType());
unsigned TypeAlignment = getTypeAlignment(Ty);
+ // If the type alignment is larger then the struct alignment, we must use
+ // a packed struct.
+ if (TypeAlignment > Alignment) {
+ assert(!Packed && "Alignment is wrong even with packed struct!");
+ return false;
+ }
+
+ if (const RecordType *RT = D->getType()->getAs<RecordType>()) {
+ const RecordDecl *RD = cast<RecordDecl>(RT->getDecl());
+ if (const PragmaPackAttr *PPA = RD->getAttr<PragmaPackAttr>()) {
+ if (PPA->getAlignment() != TypeAlignment * 8 && !Packed)
+ return false;
+ }
+ }
+
// Round up the field offset to the alignment of the field type.
uint64_t AlignedNextFieldOffsetInBytes =
llvm::RoundUpToAlignment(NextFieldOffsetInBytes, TypeAlignment);
@@ -193,6 +210,7 @@ void CGRecordLayoutBuilder::LayoutUnion(const RecordDecl *D) {
bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
assert(!D->isUnion() && "Can't call LayoutFields on a union!");
+ assert(Alignment && "Did not set alignment!");
const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(D);
diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.h b/clang/lib/CodeGen/CGRecordLayoutBuilder.h
index bca0b5c1429..ff551a4f135 100644
--- a/clang/lib/CodeGen/CGRecordLayoutBuilder.h
+++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.h
@@ -36,6 +36,9 @@ class CGRecordLayoutBuilder {
/// Packed - Whether the resulting LLVM struct will be packed or not.
bool Packed;
+ /// Alignment - Contains the alignment of the RecordDecl.
+ unsigned Alignment;
+
/// AlignmentAsLLVMStruct - Will contain the maximum alignment of all the
/// LLVM types.
unsigned AlignmentAsLLVMStruct;
@@ -69,7 +72,7 @@ class CGRecordLayoutBuilder {
llvm::SmallVector<LLVMBitFieldInfo, 16> LLVMBitFields;
CGRecordLayoutBuilder(CodeGenTypes &Types)
- : Types(Types), Packed(false), AlignmentAsLLVMStruct(1)
+ : Types(Types), Packed(false), Alignment(0), AlignmentAsLLVMStruct(1)
, BitsAvailableInLastField(0), NextFieldOffsetInBytes(0) { }
/// Layout - Will layout a RecordDecl.
OpenPOWER on IntegriCloud