On 8 November 2010 21:25, Anders Carlsson <[email protected]> wrote: > Author: andersca > Date: Mon Nov 8 23:25:47 2010 > New Revision: 118491 > > URL: http://llvm.org/viewvc/llvm-project?rev=118491&view=rev > Log: > Introduce the concept of a non-virtual base type to CGRecordLayoutBuilder > as a first step towards fixing PR6995. >
I don't think you meant to commit the printfs. Nick > Modified: > cfe/trunk/lib/CodeGen/CGRecordLayout.h > cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp > > Modified: cfe/trunk/lib/CodeGen/CGRecordLayout.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRecordLayout.h?rev=118491&r1=118490&r2=118491&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGRecordLayout.h (original) > +++ cfe/trunk/lib/CodeGen/CGRecordLayout.h Mon Nov 8 23:25:47 2010 > @@ -172,9 +172,13 @@ > void operator=(const CGRecordLayout&); // DO NOT IMPLEMENT > > private: > - /// The LLVMType corresponding to this record layout. > + /// The LLVM type corresponding to this record layout. > const llvm::Type *LLVMType; > > + /// The LLVM type for the non-virtual part of this record layout, used > for > + /// laying out the record as a base. > + const llvm::Type *BaseLLVMType; > + > /// Map from (non-bit-field) struct field to the corresponding llvm > struct > /// type field no. This info is populated by record builder. > llvm::DenseMap<const FieldDecl *, unsigned> FieldInfo; > @@ -192,14 +196,20 @@ > bool IsZeroInitializable : 1; > > public: > - CGRecordLayout(const llvm::Type *T, bool IsZeroInitializable) > - : LLVMType(T), IsZeroInitializable(IsZeroInitializable) {} > + CGRecordLayout(const llvm::Type *LLVMType, const llvm::Type > *BaseLLVMType, > + bool IsZeroInitializable) > + : LLVMType(LLVMType), BaseLLVMType(BaseLLVMType), > + IsZeroInitializable(IsZeroInitializable) {} > > /// \brief Return the LLVM type associated with this record. > const llvm::Type *getLLVMType() const { > return LLVMType; > } > > + const llvm::Type *getBaseLLVMType() const { > + return BaseLLVMType; > + } > + > /// \brief Check whether this struct can be C++ zero-initialized > /// with a zeroinitializer. > bool isZeroInitializable() const { > > Modified: cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp?rev=118491&r1=118490&r2=118491&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp Mon Nov 8 23:25:47 > 2010 > @@ -35,6 +35,24 @@ > /// 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 @@ > 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 @@ > /// 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 @@ > > 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 @@ > } > } > > +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 @@ > } > } > > + // 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::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 @@ > 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 @@ > > #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 @@ > 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"; > > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
