[cfe-commits] r125605 - /cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp

Ken Dyck kd at kendyck.com
Wed Feb 16 04:43:04 PST 2011


On Tue, Feb 15, 2011 at 5:21 PM, John McCall <rjmccall at apple.com> wrote:
> @@ -310,47 +309,46 @@
>  }
>
>  void CGRecordLayoutBuilder::LayoutBitField(const FieldDecl *D,
> -                                           uint64_t FieldOffset) {
> -  uint64_t FieldSize =
> +                                           uint64_t fieldOffset) {
> +  uint64_t fieldSize =
>     D->getBitWidth()->EvaluateAsInt(Types.getContext()).getZExtValue();
>
> -  if (FieldSize == 0)
> +  if (fieldSize == 0)
>     return;
>
> -  uint64_t NextFieldOffset = NextFieldOffsetInBytes * 8;
> -  unsigned NumBytesToAppend;
> +  uint64_t nextFieldOffsetInBits = NextFieldOffset.getQuantity() * 8;

You could use Types.getContext().toBits(NextFieldOffset) here to
eliminate the literal 8.

> +  unsigned numBytesToAppend;
>
> -  if (FieldOffset < NextFieldOffset) {
> +  if (fieldOffset < nextFieldOffsetInBits) {
>     assert(BitsAvailableInLastField && "Bitfield size mismatch!");
> -    assert(NextFieldOffsetInBytes && "Must have laid out at least one byte!");
> +    assert(!NextFieldOffset.isZero() && "Must have laid out at least one byte");
>
>     // The bitfield begins in the previous bit-field.
> -    NumBytesToAppend =
> -      llvm::RoundUpToAlignment(FieldSize - BitsAvailableInLastField, 8) / 8;
> +    numBytesToAppend =
> +      llvm::RoundUpToAlignment(fieldSize - BitsAvailableInLastField, 8) / 8;
>   } else {
> -    assert(FieldOffset % 8 == 0 && "Field offset not aligned correctly");
> +    assert(fieldOffset % 8 == 0 && "Field offset not aligned correctly");
>
>     // Append padding if necessary.
> -    AppendPadding(FieldOffset / 8, 1);
> +    AppendPadding(CharUnits::fromQuantity(fieldOffset / 8), CharUnits::One());

Replacing with Types.getContext().toCharUnitsFromBits(fieldOffset)
would eliminate the literal 8.
>
> -    NumBytesToAppend =
> -      llvm::RoundUpToAlignment(FieldSize, 8) / 8;
> +    numBytesToAppend = llvm::RoundUpToAlignment(fieldSize, 8) / 8;
>
> -    assert(NumBytesToAppend && "No bytes to append!");
> +    assert(numBytesToAppend && "No bytes to append!");
>   }
>
>   // Add the bit field info.
>   BitFields.insert(std::make_pair(D,
> -                   CGBitFieldInfo::MakeInfo(Types, D, FieldOffset, FieldSize)));
> +                   CGBitFieldInfo::MakeInfo(Types, D, fieldOffset, fieldSize)));
>
> -  AppendBytes(NumBytesToAppend);
> +  AppendBytes(CharUnits::fromQuantity(numBytesToAppend));
>
>   BitsAvailableInLastField =
> -    NextFieldOffsetInBytes * 8 - (FieldOffset + FieldSize);
> +    NextFieldOffset.getQuantity() * 8 - (fieldOffset + fieldSize);

Types.getContext().toBits(NextFieldOffset)?



> @@ -439,78 +439,97 @@
>  void CGRecordLayoutBuilder::LayoutUnion(const RecordDecl *D) {
>   assert(D->isUnion() && "Can't call LayoutUnion on a non-union record!");
>
> -  const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(D);
> -
> -  const llvm::Type *Ty = 0;
> -  uint64_t Size = 0;
> -  unsigned Align = 0;
> -
> -  bool HasOnlyZeroSizedBitFields = true;
> +  const ASTRecordLayout &layout = Types.getContext().getASTRecordLayout(D);
>
> -  unsigned FieldNo = 0;
> -  for (RecordDecl::field_iterator Field = D->field_begin(),
> -       FieldEnd = D->field_end(); Field != FieldEnd; ++Field, ++FieldNo) {
> -    assert(Layout.getFieldOffset(FieldNo) == 0 &&
> +  const llvm::Type *unionType = 0;
> +  CharUnits unionSize = CharUnits::Zero();
> +  CharUnits unionAlign = CharUnits::Zero();
> +
> +  bool hasOnlyZeroSizedBitFields = true;
> +
> +  unsigned fieldNo = 0;
> +  for (RecordDecl::field_iterator field = D->field_begin(),
> +       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 *FieldTy = LayoutUnionField(*Field, Layout);
> +    const llvm::Type *fieldType = LayoutUnionField(*field, layout);
>
> -    if (!FieldTy)
> +    if (!fieldType)
>       continue;
>
> -    HasOnlyZeroSizedBitFields = false;
> +    hasOnlyZeroSizedBitFields = false;
>
> -    unsigned FieldAlign = Types.getTargetData().getABITypeAlignment(FieldTy);
> -    uint64_t FieldSize = Types.getTargetData().getTypeAllocSize(FieldTy);
> +    CharUnits fieldAlign = CharUnits::fromQuantity(
> +                          Types.getTargetData().getABITypeAlignment(fieldType));
> +    CharUnits fieldSize = CharUnits::fromQuantity(
> +                             Types.getTargetData().getTypeAllocSize(fieldType));
>
> -    if (FieldAlign < Align)
> +    if (fieldAlign < unionAlign)
>       continue;
>
> -    if (FieldAlign > Align || FieldSize > Size) {
> -      Ty = FieldTy;
> -      Align = FieldAlign;
> -      Size = FieldSize;
> +    if (fieldAlign > unionAlign || fieldSize > unionSize) {
> +      unionType = fieldType;
> +      unionAlign = fieldAlign;
> +      unionSize = fieldSize;
>     }
>   }
>
>   // Now add our field.
> -  if (Ty) {
> -    AppendField(0, Ty);
> +  if (unionType) {
> +    AppendField(CharUnits::Zero(), unionType);
>
> -    if (getTypeAlignment(Ty) > Layout.getAlignment().getQuantity()) {
> +    if (getTypeAlignment(unionType) > layout.getAlignment()) {
>       // We need a packed struct.
>       Packed = true;
> -      Align = 1;
> +      unionAlign = CharUnits::One();
>     }
>   }
> -  if (!Align) {
> -    assert(HasOnlyZeroSizedBitFields &&
> +  if (unionAlign.isZero()) {
> +    assert(hasOnlyZeroSizedBitFields &&
>            "0-align record did not have all zero-sized bit-fields!");
> -    Align = 1;
> +    unionAlign = CharUnits::One();
>   }
>
>   // Append tail padding.
> -  uint64_t RecordSize = Layout.getSize().getQuantity();
> -  if (RecordSize > Size)
> -    AppendPadding(RecordSize, Align);
> +  CharUnits recordSize = layout.getSize();
> +  if (recordSize > unionSize)
> +    AppendPadding(recordSize, unionAlign);
>  }
>
>  void CGRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *base,
> -                                       uint64_t baseOffsetInBits) {
> -  uint64_t baseOffsetInBytes = baseOffsetInBits / 8;
> -  AppendPadding(baseOffsetInBytes, 1);
> +                                       const CGRecordLayout &baseLayout,
> +                                       CharUnits baseOffset) {
> +  AppendPadding(baseOffset, CharUnits::One());
>
>   const ASTRecordLayout &baseASTLayout
>     = Types.getContext().getASTRecordLayout(base);
>
> -  // FIXME: use a better type than [sizeof(base) x i8].
> -  // We could use the base layout's subobject type as the actualy
> -  // subobject type in the layout if its size is the nvsize of the
> -  // base, or if we'd need padding out to the enclosing object anyhow.
> -  AppendBytes(baseASTLayout.getNonVirtualSize());
> +  // Fields and bases can be laid out in the tail padding of previous
> +  // bases.  If this happens, we need to allocate the base as an i8
> +  // array; otherwise, we can use the subobject type.  However,
> +  // actually doing that would require knowledge of what immediately
> +  // follows this base in the layout, so instead we do a conservative
> +  // approximation, which is to use the base subobject type if it
> +  // has the same LLVM storage size as the nvsize.
> +
> +  // The nvsize, i.e. the unpadded size of the base class.
> +  CharUnits nvsize = baseASTLayout.getNonVirtualSize();
> +
> +#if 0
> +  const llvm::StructType *subobjectType = baseLayout.getBaseSubobjectLLVMType();
> +  const llvm::StructLayout *baseLLVMLayout =
> +    Types.getTargetData().getStructLayout(subobjectType);
> +  CharUnits stsize = CharUnits::fromQuantity(baseLLVMLayout->getSizeInBytes());
> +
> +  if (nvsize == stsize)
> +    AppendField(baseOffset, subobjectType);
> +  else
> +#endif

Did you mean to keep this dead block for later?

> @@ -697,84 +715,84 @@
>  void CGRecordLayoutBuilder::AppendTailPadding(uint64_t RecordSize) {
>   assert(RecordSize % 8 == 0 && "Invalid record size!");
>
> -  uint64_t RecordSizeInBytes = RecordSize / 8;
> -  assert(NextFieldOffsetInBytes <= RecordSizeInBytes && "Size mismatch!");
> +  CharUnits RecordSizeInBytes = CharUnits::fromQuantity(RecordSize / 8);

Context.toCharUnitsFromBits(RecordSize)?

-Ken




More information about the cfe-commits mailing list