<div><div class="gmail_quote">On 8 November 2010 21:25, Anders Carlsson <span dir="ltr"><<a href="mailto:andersca@mac.com">andersca@mac.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Author: andersca<br>
Date: Mon Nov 8 23:25:47 2010<br>
New Revision: 118491<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=118491&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=118491&view=rev</a><br>
Log:<br>
Introduce the concept of a non-virtual base type to CGRecordLayoutBuilder as a first step towards fixing PR6995.<br></blockquote><div><br></div><meta http-equiv="content-type" content="text/html; charset=utf-8">I don't think you meant to commit the printfs.<div>
<br></div><div>Nick</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Modified:<br>
cfe/trunk/lib/CodeGen/CGRecordLayout.h<br>
cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGRecordLayout.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRecordLayout.h?rev=118491&r1=118490&r2=118491&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRecordLayout.h?rev=118491&r1=118490&r2=118491&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGRecordLayout.h (original)<br>
+++ cfe/trunk/lib/CodeGen/CGRecordLayout.h Mon Nov 8 23:25:47 2010<br>
@@ -172,9 +172,13 @@<br>
void operator=(const CGRecordLayout&); // DO NOT IMPLEMENT<br>
<br>
private:<br>
- /// The LLVMType corresponding to this record layout.<br>
+ /// The LLVM type corresponding to this record layout.<br>
const llvm::Type *LLVMType;<br>
<br>
+ /// The LLVM type for the non-virtual part of this record layout, used for<br>
+ /// laying out the record as a base.<br>
+ const llvm::Type *BaseLLVMType;<br>
+<br>
/// Map from (non-bit-field) struct field to the corresponding llvm struct<br>
/// type field no. This info is populated by record builder.<br>
llvm::DenseMap<const FieldDecl *, unsigned> FieldInfo;<br>
@@ -192,14 +196,20 @@<br>
bool IsZeroInitializable : 1;<br>
<br>
public:<br>
- CGRecordLayout(const llvm::Type *T, bool IsZeroInitializable)<br>
- : LLVMType(T), IsZeroInitializable(IsZeroInitializable) {}<br>
+ CGRecordLayout(const llvm::Type *LLVMType, const llvm::Type *BaseLLVMType,<br>
+ bool IsZeroInitializable)<br>
+ : LLVMType(LLVMType), BaseLLVMType(BaseLLVMType),<br>
+ IsZeroInitializable(IsZeroInitializable) {}<br>
<br>
/// \brief Return the LLVM type associated with this record.<br>
const llvm::Type *getLLVMType() const {<br>
return LLVMType;<br>
}<br>
<br>
+ const llvm::Type *getBaseLLVMType() const {<br>
+ return BaseLLVMType;<br>
+ }<br>
+<br>
/// \brief Check whether this struct can be C++ zero-initialized<br>
/// with a zeroinitializer.<br>
bool isZeroInitializable() const {<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp?rev=118491&r1=118490&r2=118491&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp?rev=118491&r1=118490&r2=118491&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp Mon Nov 8 23:25:47 2010<br>
@@ -35,6 +35,24 @@<br>
/// FieldTypes - Holds the LLVM types that the struct is created from.<br>
std::vector<const llvm::Type *> FieldTypes;<br>
<br>
+ /// NonVirtualBaseFieldTypes - Holds the LLVM types for the non-virtual part<br>
+ /// of the struct. For example, consider:<br>
+ ///<br>
+ /// struct A { int i; };<br>
+ /// struct B { void *v; };<br>
+ /// struct C : virtual A, B { };<br>
+ ///<br>
+ /// The LLVM type of C will be<br>
+ /// %struct.C = type { i32 (...)**, %struct.A, i32, %struct.B }<br>
+ ///<br>
+ /// And the LLVM type of the non-virtual base struct will be<br>
+ /// %struct.C.base = type { i32 (...)**, %struct.A, i32 }<br>
+ std::vector<const llvm::Type *> NonVirtualBaseFieldTypes;<br>
+<br>
+ /// NonVirtualBaseTypeIsSameAsCompleteType - Whether the non-virtual part of<br>
+ /// the struct is equivalent to the complete struct.<br>
+ bool NonVirtualBaseTypeIsSameAsCompleteType;<br>
+<br>
/// LLVMFieldInfo - Holds a field and its corresponding LLVM field number.<br>
typedef std::pair<const FieldDecl *, unsigned> LLVMFieldInfo;<br>
llvm::SmallVector<LLVMFieldInfo, 16> LLVMFields;<br>
@@ -92,6 +110,9 @@<br>
void LayoutNonVirtualBases(const CXXRecordDecl *RD,<br>
const ASTRecordLayout &Layout);<br>
<br>
+ /// ComputeNonVirtualBaseType - Compute the non-virtual base field types.<br>
+ void ComputeNonVirtualBaseType(const CXXRecordDecl *RD);<br>
+<br>
/// LayoutField - layout a single field. Returns false if the operation failed<br>
/// because the current struct is not packed.<br>
bool LayoutField(const FieldDecl *D, uint64_t FieldOffset);<br>
@@ -106,6 +127,10 @@<br>
/// struct size is a multiple of the field alignment.<br>
void AppendPadding(uint64_t FieldOffsetInBytes, unsigned FieldAlignment);<br>
<br>
+ /// getByteArrayType - Returns a byte array type with the given number of<br>
+ /// elements.<br>
+ const llvm::Type *getByteArrayType(uint64_t NumBytes);<br>
+<br>
/// AppendBytes - Append a given number of bytes to the record.<br>
void AppendBytes(uint64_t NumBytes);<br>
<br>
@@ -122,8 +147,8 @@<br>
<br>
public:<br>
CGRecordLayoutBuilder(CodeGenTypes &Types)<br>
- : IsZeroInitializable(true), Packed(false), Types(Types),<br>
- Alignment(0), AlignmentAsLLVMStruct(1),<br>
+ : NonVirtualBaseTypeIsSameAsCompleteType(false), IsZeroInitializable(true),<br>
+ Packed(false), Types(Types), Alignment(0), AlignmentAsLLVMStruct(1),<br>
BitsAvailableInLastField(0), NextFieldOffsetInBytes(0) { }<br>
<br>
/// Layout - Will layout a RecordDecl.<br>
@@ -520,13 +545,50 @@<br>
}<br>
}<br>
<br>
+void<br>
+CGRecordLayoutBuilder::ComputeNonVirtualBaseType(const CXXRecordDecl *RD) {<br>
+ const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(RD);<br>
+<br>
+ uint64_t AlignedNonVirtualTypeSize =<br>
+ llvm::RoundUpToAlignment(Layout.getNonVirtualSize(),<br>
+ Layout.getNonVirtualAlign()) / 8;<br>
+<br>
+<br>
+ // First check if we can use the same fields as for the complete class.<br>
+ if (AlignedNonVirtualTypeSize == Layout.getSize() / 8) {<br>
+ NonVirtualBaseTypeIsSameAsCompleteType = true;<br>
+ return;<br>
+ }<br>
+<br>
+ NonVirtualBaseFieldTypes = FieldTypes;<br>
+<br>
+ // Check if we need padding.<br>
+ uint64_t AlignedNextFieldOffset =<br>
+ llvm::RoundUpToAlignment(NextFieldOffsetInBytes, AlignmentAsLLVMStruct);<br>
+<br>
+ assert(AlignedNextFieldOffset <= AlignedNonVirtualTypeSize &&<br>
+ "Size mismatch!");<br>
+<br>
+ if (AlignedNonVirtualTypeSize == AlignedNextFieldOffset) {<br>
+ // We don't need any padding.<br>
+ return;<br>
+ }<br>
+<br>
+ uint64_t NumBytes = AlignedNonVirtualTypeSize - AlignedNextFieldOffset;<br>
+ NonVirtualBaseFieldTypes.push_back(getByteArrayType(NumBytes));<br>
+<br>
+ printf("nvts: %llu, aligned nfo: %llu\n",<br>
+ AlignedNonVirtualTypeSize, AlignedNextFieldOffset);<br>
+}<br>
+<br>
bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {<br>
assert(!D->isUnion() && "Can't call LayoutFields on a union!");<br>
assert(Alignment && "Did not set alignment!");<br>
<br>
const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(D);<br>
<br>
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D))<br>
+ const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D);<br>
+ if (RD)<br>
LayoutNonVirtualBases(RD, Layout);<br>
<br>
unsigned FieldNo = 0;<br>
@@ -540,6 +602,14 @@<br>
}<br>
}<br>
<br>
+ // We've laid out the non-virtual bases and the fields, now compute the<br>
+ // non-virtual base field types.<br>
+ if (RD)<br>
+ ComputeNonVirtualBaseType(RD);<br>
+<br>
+ // FIXME: Lay out the virtual bases instead of just treating them as tail<br>
+ // padding.<br>
+<br>
// Append tail padding if necessary.<br>
AppendTailPadding(Layout.getSize());<br>
<br>
@@ -595,16 +665,22 @@<br>
}<br>
}<br>
<br>
-void CGRecordLayoutBuilder::AppendBytes(uint64_t NumBytes) {<br>
- if (NumBytes == 0)<br>
- return;<br>
+const llvm::Type *CGRecordLayoutBuilder::getByteArrayType(uint64_t NumBytes) {<br>
+ assert(NumBytes != 0 && "Empty byte array's aren't allowed.");<br>
<br>
const llvm::Type *Ty = llvm::Type::getInt8Ty(Types.getLLVMContext());<br>
if (NumBytes > 1)<br>
Ty = llvm::ArrayType::get(Ty, NumBytes);<br>
<br>
+ return Ty;<br>
+}<br>
+<br>
+void CGRecordLayoutBuilder::AppendBytes(uint64_t NumBytes) {<br>
+ if (NumBytes == 0)<br>
+ return;<br>
+<br>
// Append the padding field<br>
- AppendField(NextFieldOffsetInBytes, Ty);<br>
+ AppendField(NextFieldOffsetInBytes, getByteArrayType(NumBytes));<br>
}<br>
<br>
unsigned CGRecordLayoutBuilder::getTypeAlignment(const llvm::Type *Ty) const {<br>
@@ -658,8 +734,18 @@<br>
Builder.FieldTypes,<br>
Builder.Packed);<br>
<br>
+ const llvm::Type *BaseTy = 0;<br>
+ if (isa<CXXRecordDecl>(D)) {<br>
+ if (Builder.NonVirtualBaseTypeIsSameAsCompleteType)<br>
+ BaseTy = Ty;<br>
+ else if (!Builder.NonVirtualBaseFieldTypes.empty())<br>
+ BaseTy = llvm::StructType::get(getLLVMContext(),<br>
+ Builder.NonVirtualBaseFieldTypes,<br>
+ Builder.Packed);<br>
+ }<br>
+<br>
CGRecordLayout *RL =<br>
- new CGRecordLayout(Ty, Builder.IsZeroInitializable);<br>
+ new CGRecordLayout(Ty, BaseTy, Builder.IsZeroInitializable);<br>
<br>
// Add all the non-virtual base field numbers.<br>
RL->NonVirtualBaseFields.insert(Builder.LLVMNonVirtualBases.begin(),<br>
@@ -684,10 +770,22 @@<br>
<br>
#ifndef NDEBUG<br>
// Verify that the computed LLVM struct size matches the AST layout size.<br>
- uint64_t TypeSizeInBits = getContext().getASTRecordLayout(D).getSize();<br>
+ const ASTRecordLayout &Layout = getContext().getASTRecordLayout(D);<br>
+<br>
+ uint64_t TypeSizeInBits = Layout.getSize();<br>
assert(TypeSizeInBits == getTargetData().getTypeAllocSizeInBits(Ty) &&<br>
"Type size mismatch!");<br>
<br>
+ if (BaseTy) {<br>
+ uint64_t AlignedNonVirtualTypeSizeInBits =<br>
+ llvm::RoundUpToAlignment(Layout.getNonVirtualSize(),<br>
+ Layout.getNonVirtualAlign());<br>
+<br>
+ assert(AlignedNonVirtualTypeSizeInBits ==<br>
+ getTargetData().getTypeAllocSizeInBits(BaseTy) &&<br>
+ "Type size mismatch!");<br>
+ }<br>
+<br>
// Verify that the LLVM and AST field offsets agree.<br>
const llvm::StructType *ST =<br>
dyn_cast<llvm::StructType>(RL->getLLVMType());<br>
@@ -730,6 +828,8 @@<br>
void CGRecordLayout::print(llvm::raw_ostream &OS) const {<br>
OS << "<CGRecordLayout\n";<br>
OS << " LLVMType:" << *LLVMType << "\n";<br>
+ if (BaseLLVMType)<br>
+ OS << " BaseLLVMType:" << *BaseLLVMType << "\n";<br>
OS << " IsZeroInitializable:" << IsZeroInitializable << "\n";<br>
OS << " BitFields:[\n";<br>
<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>