summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2010-11-09 05:25:47 +0000
committerAnders Carlsson <andersca@mac.com>2010-11-09 05:25:47 +0000
commitc1351cac17c2357866132aeaa69706fc84bd4201 (patch)
tree253742331d40b7497411859b5cdf45e9727a9288 /clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
parent25e84078e38ce3363bf3fd8342fea7e8bdfc0abd (diff)
downloadbcm5719-llvm-c1351cac17c2357866132aeaa69706fc84bd4201.tar.gz
bcm5719-llvm-c1351cac17c2357866132aeaa69706fc84bd4201.zip
Introduce the concept of a non-virtual base type to CGRecordLayoutBuilder as a first step towards fixing PR6995.
llvm-svn: 118491
Diffstat (limited to 'clang/lib/CodeGen/CGRecordLayoutBuilder.cpp')
-rw-r--r--clang/lib/CodeGen/CGRecordLayoutBuilder.cpp118
1 files changed, 109 insertions, 9 deletions
diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
index 6f53cafa77c..c3f45a35fb4 100644
--- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -35,6 +35,24 @@ public:
/// FieldTypes - Holds the LLVM types that the struct is created from.
std::vector<const llvm::Type *> FieldTypes;
+ /// NonVirtualBaseFieldTypes - Holds the LLVM types for the non-virtual part
+ /// of the struct. For example, consider:
+ ///
+ /// struct A { int i; };
+ /// struct B { void *v; };
+ /// struct C : virtual A, B { };
+ ///
+ /// The LLVM type of C will be
+ /// %struct.C = type { i32 (...)**, %struct.A, i32, %struct.B }
+ ///
+ /// And the LLVM type of the non-virtual base struct will be
+ /// %struct.C.base = type { i32 (...)**, %struct.A, i32 }
+ std::vector<const llvm::Type *> NonVirtualBaseFieldTypes;
+
+ /// NonVirtualBaseTypeIsSameAsCompleteType - Whether the non-virtual part of
+ /// the struct is equivalent to the complete struct.
+ bool NonVirtualBaseTypeIsSameAsCompleteType;
+
/// LLVMFieldInfo - Holds a field and its corresponding LLVM field number.
typedef std::pair<const FieldDecl *, unsigned> LLVMFieldInfo;
llvm::SmallVector<LLVMFieldInfo, 16> LLVMFields;
@@ -92,6 +110,9 @@ private:
void LayoutNonVirtualBases(const CXXRecordDecl *RD,
const ASTRecordLayout &Layout);
+ /// ComputeNonVirtualBaseType - Compute the non-virtual base field types.
+ void ComputeNonVirtualBaseType(const CXXRecordDecl *RD);
+
/// LayoutField - layout a single field. Returns false if the operation failed
/// because the current struct is not packed.
bool LayoutField(const FieldDecl *D, uint64_t FieldOffset);
@@ -106,6 +127,10 @@ private:
/// struct size is a multiple of the field alignment.
void AppendPadding(uint64_t FieldOffsetInBytes, unsigned FieldAlignment);
+ /// getByteArrayType - Returns a byte array type with the given number of
+ /// elements.
+ const llvm::Type *getByteArrayType(uint64_t NumBytes);
+
/// AppendBytes - Append a given number of bytes to the record.
void AppendBytes(uint64_t NumBytes);
@@ -122,8 +147,8 @@ private:
public:
CGRecordLayoutBuilder(CodeGenTypes &Types)
- : IsZeroInitializable(true), Packed(false), Types(Types),
- Alignment(0), AlignmentAsLLVMStruct(1),
+ : NonVirtualBaseTypeIsSameAsCompleteType(false), IsZeroInitializable(true),
+ Packed(false), Types(Types), Alignment(0), AlignmentAsLLVMStruct(1),
BitsAvailableInLastField(0), NextFieldOffsetInBytes(0) { }
/// Layout - Will layout a RecordDecl.
@@ -520,13 +545,50 @@ CGRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD,
}
}
+void
+CGRecordLayoutBuilder::ComputeNonVirtualBaseType(const CXXRecordDecl *RD) {
+ const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(RD);
+
+ uint64_t AlignedNonVirtualTypeSize =
+ llvm::RoundUpToAlignment(Layout.getNonVirtualSize(),
+ Layout.getNonVirtualAlign()) / 8;
+
+
+ // First check if we can use the same fields as for the complete class.
+ if (AlignedNonVirtualTypeSize == Layout.getSize() / 8) {
+ NonVirtualBaseTypeIsSameAsCompleteType = true;
+ return;
+ }
+
+ NonVirtualBaseFieldTypes = FieldTypes;
+
+ // Check if we need padding.
+ uint64_t AlignedNextFieldOffset =
+ llvm::RoundUpToAlignment(NextFieldOffsetInBytes, AlignmentAsLLVMStruct);
+
+ assert(AlignedNextFieldOffset <= AlignedNonVirtualTypeSize &&
+ "Size mismatch!");
+
+ if (AlignedNonVirtualTypeSize == AlignedNextFieldOffset) {
+ // We don't need any padding.
+ return;
+ }
+
+ uint64_t NumBytes = AlignedNonVirtualTypeSize - AlignedNextFieldOffset;
+ NonVirtualBaseFieldTypes.push_back(getByteArrayType(NumBytes));
+
+ printf("nvts: %llu, aligned nfo: %llu\n",
+ AlignedNonVirtualTypeSize, AlignedNextFieldOffset);
+}
+
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);
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D))
+ const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D);
+ if (RD)
LayoutNonVirtualBases(RD, Layout);
unsigned FieldNo = 0;
@@ -540,6 +602,14 @@ bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
}
}
+ // We've laid out the non-virtual bases and the fields, now compute the
+ // non-virtual base field types.
+ if (RD)
+ ComputeNonVirtualBaseType(RD);
+
+ // FIXME: Lay out the virtual bases instead of just treating them as tail
+ // padding.
+
// Append tail padding if necessary.
AppendTailPadding(Layout.getSize());
@@ -595,16 +665,22 @@ void CGRecordLayoutBuilder::AppendPadding(uint64_t FieldOffsetInBytes,
}
}
-void CGRecordLayoutBuilder::AppendBytes(uint64_t NumBytes) {
- if (NumBytes == 0)
- return;
+const llvm::Type *CGRecordLayoutBuilder::getByteArrayType(uint64_t NumBytes) {
+ assert(NumBytes != 0 && "Empty byte array's aren't allowed.");
const llvm::Type *Ty = llvm::Type::getInt8Ty(Types.getLLVMContext());
if (NumBytes > 1)
Ty = llvm::ArrayType::get(Ty, NumBytes);
+ return Ty;
+}
+
+void CGRecordLayoutBuilder::AppendBytes(uint64_t NumBytes) {
+ if (NumBytes == 0)
+ return;
+
// Append the padding field
- AppendField(NextFieldOffsetInBytes, Ty);
+ AppendField(NextFieldOffsetInBytes, getByteArrayType(NumBytes));
}
unsigned CGRecordLayoutBuilder::getTypeAlignment(const llvm::Type *Ty) const {
@@ -658,8 +734,18 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) {
Builder.FieldTypes,
Builder.Packed);
+ const llvm::Type *BaseTy = 0;
+ if (isa<CXXRecordDecl>(D)) {
+ if (Builder.NonVirtualBaseTypeIsSameAsCompleteType)
+ BaseTy = Ty;
+ else if (!Builder.NonVirtualBaseFieldTypes.empty())
+ BaseTy = llvm::StructType::get(getLLVMContext(),
+ Builder.NonVirtualBaseFieldTypes,
+ Builder.Packed);
+ }
+
CGRecordLayout *RL =
- new CGRecordLayout(Ty, Builder.IsZeroInitializable);
+ new CGRecordLayout(Ty, BaseTy, Builder.IsZeroInitializable);
// Add all the non-virtual base field numbers.
RL->NonVirtualBaseFields.insert(Builder.LLVMNonVirtualBases.begin(),
@@ -684,10 +770,22 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) {
#ifndef NDEBUG
// Verify that the computed LLVM struct size matches the AST layout size.
- uint64_t TypeSizeInBits = getContext().getASTRecordLayout(D).getSize();
+ const ASTRecordLayout &Layout = getContext().getASTRecordLayout(D);
+
+ uint64_t TypeSizeInBits = Layout.getSize();
assert(TypeSizeInBits == getTargetData().getTypeAllocSizeInBits(Ty) &&
"Type size mismatch!");
+ if (BaseTy) {
+ uint64_t AlignedNonVirtualTypeSizeInBits =
+ llvm::RoundUpToAlignment(Layout.getNonVirtualSize(),
+ Layout.getNonVirtualAlign());
+
+ assert(AlignedNonVirtualTypeSizeInBits ==
+ getTargetData().getTypeAllocSizeInBits(BaseTy) &&
+ "Type size mismatch!");
+ }
+
// Verify that the LLVM and AST field offsets agree.
const llvm::StructType *ST =
dyn_cast<llvm::StructType>(RL->getLLVMType());
@@ -730,6 +828,8 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) {
void CGRecordLayout::print(llvm::raw_ostream &OS) const {
OS << "<CGRecordLayout\n";
OS << " LLVMType:" << *LLVMType << "\n";
+ if (BaseLLVMType)
+ OS << " BaseLLVMType:" << *BaseLLVMType << "\n";
OS << " IsZeroInitializable:" << IsZeroInitializable << "\n";
OS << " BitFields:[\n";
OpenPOWER on IntegriCloud