diff options
Diffstat (limited to 'lib/CodeGen/CGRecordLayoutBuilder.cpp')
-rw-r--r-- | lib/CodeGen/CGRecordLayoutBuilder.cpp | 69 |
1 files changed, 40 insertions, 29 deletions
diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp index 0d72f85..2b07baf 100644 --- a/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -18,6 +18,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" #include "clang/AST/RecordLayout.h" +#include "clang/Frontend/CodeGenOptions.h" #include "CodeGenTypes.h" #include "CGCXXABI.h" #include "llvm/DerivedTypes.h" @@ -34,7 +35,7 @@ class CGRecordLayoutBuilder { public: /// FieldTypes - Holds the LLVM types that the struct is created from. /// - llvm::SmallVector<const llvm::Type *, 16> FieldTypes; + llvm::SmallVector<llvm::Type *, 16> FieldTypes; /// BaseSubobjectType - Holds the LLVM type for the non-virtual part /// of the struct. For example, consider: @@ -51,7 +52,7 @@ public: /// /// This only gets initialized if the base subobject type is /// different from the complete-object type. - const llvm::StructType *BaseSubobjectType; + llvm::StructType *BaseSubobjectType; /// FieldInfo - Holds a field and its corresponding LLVM field number. llvm::DenseMap<const FieldDecl *, unsigned> Fields; @@ -108,8 +109,8 @@ private: /// LayoutUnionField - Will layout a field in an union and return the type /// that the field will have. - const llvm::Type *LayoutUnionField(const FieldDecl *Field, - const ASTRecordLayout &Layout); + llvm::Type *LayoutUnionField(const FieldDecl *Field, + const ASTRecordLayout &Layout); /// LayoutUnion - Will layout a union RecordDecl. void LayoutUnion(const RecordDecl *D); @@ -150,7 +151,7 @@ private: void LayoutBitField(const FieldDecl *D, uint64_t FieldOffset); /// AppendField - Appends a field with the given offset and type. - void AppendField(CharUnits fieldOffset, const llvm::Type *FieldTy); + void AppendField(CharUnits fieldOffset, llvm::Type *FieldTy); /// AppendPadding - Appends enough padding bytes so that the total /// struct size is a multiple of the field alignment. @@ -164,7 +165,7 @@ private: /// getByteArrayType - Returns a byte array type with the given number of /// elements. - const llvm::Type *getByteArrayType(CharUnits NumBytes); + llvm::Type *getByteArrayType(CharUnits NumBytes); /// AppendBytes - Append a given number of bytes to the record. void AppendBytes(CharUnits numBytes); @@ -229,7 +230,7 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types, uint64_t FieldSize, uint64_t ContainingTypeSizeInBits, unsigned ContainingTypeAlign) { - const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(FD->getType()); + const llvm::Type *Ty = Types.ConvertTypeForMem(FD->getType()); CharUnits TypeSizeInBytes = CharUnits::fromQuantity(Types.getTargetData().getTypeAllocSize(Ty)); uint64_t TypeSizeInBits = Types.getContext().toBits(TypeSizeInBytes); @@ -268,6 +269,18 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types, unsigned AccessedTargetBits = 0; // The number of target bits accessed. unsigned AccessWidth = TypeSizeInBits; // The current access width to attempt. + // If requested, widen the initial bit-field access to be register sized. The + // theory is that this is most likely to allow multiple accesses into the same + // structure to be coalesced, and that the backend should be smart enough to + // narrow the store if no coalescing is ever done. + // + // The subsequent code will handle align these access to common boundaries and + // guaranteeing that we do not access past the end of the structure. + if (Types.getCodeGenOpts().UseRegisterSizedBitfieldAccess) { + if (AccessWidth < Types.getTarget().getRegisterWidth()) + AccessWidth = Types.getTarget().getRegisterWidth(); + } + // Round down from the field offset to find the first access position that is // at an aligned offset of the initial access type. uint64_t AccessStart = FieldOffset - (FieldOffset % AccessWidth); @@ -427,7 +440,7 @@ bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D, CharUnits fieldOffsetInBytes = Types.getContext().toCharUnitsFromBits(fieldOffset); - const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(D->getType()); + llvm::Type *Ty = Types.ConvertTypeForMem(D->getType()); CharUnits typeAlignment = getTypeAlignment(Ty); // If the type alignment is larger then the struct alignment, we must use @@ -475,7 +488,7 @@ bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D, return true; } -const llvm::Type * +llvm::Type * CGRecordLayoutBuilder::LayoutUnionField(const FieldDecl *Field, const ASTRecordLayout &Layout) { if (Field->isBitField()) { @@ -486,7 +499,7 @@ CGRecordLayoutBuilder::LayoutUnionField(const FieldDecl *Field, if (FieldSize == 0) return 0; - const llvm::Type *FieldTy = llvm::Type::getInt8Ty(Types.getLLVMContext()); + llvm::Type *FieldTy = llvm::Type::getInt8Ty(Types.getLLVMContext()); CharUnits NumBytesToAppend = Types.getContext().toCharUnitsFromBits( llvm::RoundUpToAlignment(FieldSize, Types.getContext().Target.getCharAlign())); @@ -502,7 +515,7 @@ CGRecordLayoutBuilder::LayoutUnionField(const FieldDecl *Field, // This is a regular union field. Fields[Field] = 0; - return Types.ConvertTypeForMemRecursive(Field->getType()); + return Types.ConvertTypeForMem(Field->getType()); } void CGRecordLayoutBuilder::LayoutUnion(const RecordDecl *D) { @@ -510,7 +523,7 @@ void CGRecordLayoutBuilder::LayoutUnion(const RecordDecl *D) { const ASTRecordLayout &layout = Types.getContext().getASTRecordLayout(D); - const llvm::Type *unionType = 0; + llvm::Type *unionType = 0; CharUnits unionSize = CharUnits::Zero(); CharUnits unionAlign = CharUnits::Zero(); @@ -521,7 +534,7 @@ void CGRecordLayoutBuilder::LayoutUnion(const RecordDecl *D) { fieldEnd = D->field_end(); field != fieldEnd; ++field, ++fieldNo) { assert(layout.getFieldOffset(fieldNo) == 0 && "Union field offset did not start at the beginning of record!"); - const llvm::Type *fieldType = LayoutUnionField(*field, layout); + llvm::Type *fieldType = LayoutUnionField(*field, layout); if (!fieldType) continue; @@ -586,10 +599,8 @@ void CGRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *base, // approximation, which is to use the base subobject type if it // has the same LLVM storage size as the nvsize. - const llvm::StructType *subobjectType = baseLayout.getBaseSubobjectLLVMType(); + llvm::StructType *subobjectType = baseLayout.getBaseSubobjectLLVMType(); AppendField(baseOffset, subobjectType); - - Types.addBaseSubobjectTypeName(base, baseLayout); } void CGRecordLayoutBuilder::LayoutNonVirtualBase(const CXXRecordDecl *base, @@ -723,13 +734,14 @@ CGRecordLayoutBuilder::ComputeNonVirtualBaseType(const CXXRecordDecl *RD) { FieldTypes.push_back(getByteArrayType(NumBytes)); } - BaseSubobjectType = llvm::StructType::get(Types.getLLVMContext(), - FieldTypes, Packed); + + BaseSubobjectType = llvm::StructType::createNamed(Types.getLLVMContext(), "", + FieldTypes, Packed); + Types.addRecordTypeName(RD, BaseSubobjectType, ".base"); - if (needsPadding) { - // Pull the padding back off. + // Pull the padding back off. + if (needsPadding) FieldTypes.pop_back(); - } return true; } @@ -806,7 +818,7 @@ void CGRecordLayoutBuilder::AppendTailPadding(CharUnits RecordSize) { } void CGRecordLayoutBuilder::AppendField(CharUnits fieldOffset, - const llvm::Type *fieldType) { + llvm::Type *fieldType) { CharUnits fieldSize = CharUnits::fromQuantity(Types.getTargetData().getTypeAllocSize(fieldType)); @@ -852,10 +864,10 @@ bool CGRecordLayoutBuilder::ResizeLastBaseFieldIfNecessary(CharUnits offset) { return true; } -const llvm::Type *CGRecordLayoutBuilder::getByteArrayType(CharUnits numBytes) { +llvm::Type *CGRecordLayoutBuilder::getByteArrayType(CharUnits numBytes) { assert(!numBytes.isZero() && "Empty byte arrays aren't allowed."); - const llvm::Type *Ty = llvm::Type::getInt8Ty(Types.getLLVMContext()); + llvm::Type *Ty = llvm::Type::getInt8Ty(Types.getLLVMContext()); if (numBytes > CharUnits::One()) Ty = llvm::ArrayType::get(Ty, numBytes.getQuantity()); @@ -911,17 +923,16 @@ void CGRecordLayoutBuilder::CheckZeroInitializable(QualType T) { } } -CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) { +CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D, + llvm::StructType *Ty) { CGRecordLayoutBuilder Builder(*this); Builder.Layout(D); - const llvm::StructType *Ty = llvm::StructType::get(getLLVMContext(), - Builder.FieldTypes, - Builder.Packed); + Ty->setBody(Builder.FieldTypes, Builder.Packed); // If we're in C++, compute the base subobject type. - const llvm::StructType *BaseTy = 0; + llvm::StructType *BaseTy = 0; if (isa<CXXRecordDecl>(D)) { BaseTy = Builder.BaseSubobjectType; if (!BaseTy) BaseTy = Ty; |