[cfe-commits] r118491 - in /cfe/trunk/lib/CodeGen: CGRecordLayout.h CGRecordLayoutBuilder.cpp
Nick Lewycky
nlewycky at google.com
Mon Nov 8 21:45:57 PST 2010
On 8 November 2010 21:25, Anders Carlsson <andersca at mac.com> 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
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20101108/aa765bed/attachment.html>
More information about the cfe-commits
mailing list