<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>