[cfe-commits] r142694 - in /cfe/trunk: include/clang/AST/RecordLayout.h lib/AST/RecordLayout.cpp lib/AST/RecordLayoutBuilder.cpp test/Sema/ms_class_layout.cpp
Eli Friedman
eli.friedman at gmail.com
Fri Oct 21 15:49:56 PDT 2011
Author: efriedma
Date: Fri Oct 21 17:49:56 2011
New Revision: 142694
URL: http://llvm.org/viewvc/llvm-project?rev=142694&view=rev
Log:
More ASTRecordLayout changes for MS ABI; based on patch by r4start.
Modified:
cfe/trunk/include/clang/AST/RecordLayout.h
cfe/trunk/lib/AST/RecordLayout.cpp
cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
cfe/trunk/test/Sema/ms_class_layout.cpp
Modified: cfe/trunk/include/clang/AST/RecordLayout.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecordLayout.h?rev=142694&r1=142693&r2=142694&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecordLayout.h (original)
+++ cfe/trunk/include/clang/AST/RecordLayout.h Fri Oct 21 17:49:56 2011
@@ -62,8 +62,11 @@
/// (either a base or a member). Will be zero if the class doesn't contain
/// any empty subobjects.
CharUnits SizeOfLargestEmptySubobject;
-
- /// VBPtrOffset - Virtual base table offset.
+
+ /// VFPtrOffset - Virtual function table offset (Microsoft-only).
+ CharUnits VFPtrOffset;
+
+ /// VBPtrOffset - Virtual base table offset (Microsoft-only).
CharUnits VBPtrOffset;
/// PrimaryBase - The primary base info for this record.
@@ -92,7 +95,8 @@
// Constructor for C++ records.
typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy;
ASTRecordLayout(const ASTContext &Ctx,
- CharUnits size, CharUnits alignment, CharUnits vbptroffset,
+ CharUnits size, CharUnits alignment,
+ CharUnits vfptroffset, CharUnits vbptroffset,
CharUnits datasize,
const uint64_t *fieldoffsets, unsigned fieldcount,
CharUnits nonvirtualsize, CharUnits nonvirtualalign,
@@ -204,7 +208,17 @@
return CXXInfo->SizeOfLargestEmptySubobject;
}
+ /// getVFPtrOffset - Get the offset for virtual function table pointer.
+ /// This is only meaningful with the Microsoft ABI.
+ CharUnits getVFPtrOffset() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+ return CXXInfo->VFPtrOffset;
+ }
+
+ /// getVBPtrOffset - Get the offset for virtual base table pointer.
+ /// This is only meaningful with the Microsoft ABI.
CharUnits getVBPtrOffset() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
return CXXInfo->VBPtrOffset;
}
};
Modified: cfe/trunk/lib/AST/RecordLayout.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayout.cpp?rev=142694&r1=142693&r2=142694&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayout.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayout.cpp Fri Oct 21 17:49:56 2011
@@ -43,7 +43,8 @@
// Constructor for C++ records.
ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx,
CharUnits size, CharUnits alignment,
- CharUnits vbptroffset, CharUnits datasize,
+ CharUnits vfptroffset, CharUnits vbptroffset,
+ CharUnits datasize,
const uint64_t *fieldoffsets,
unsigned fieldcount,
CharUnits nonvirtualsize,
@@ -68,6 +69,7 @@
CXXInfo->SizeOfLargestEmptySubobject = SizeOfLargestEmptySubobject;
CXXInfo->BaseOffsets = BaseOffsets;
CXXInfo->VBaseOffsets = VBaseOffsets;
+ CXXInfo->VFPtrOffset = vfptroffset;
CXXInfo->VBPtrOffset = vbptroffset;
#ifndef NDEBUG
Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=142694&r1=142693&r2=142694&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Fri Oct 21 17:49:56 2011
@@ -592,6 +592,9 @@
/// out is virtual.
bool PrimaryBaseIsVirtual;
+ /// VFPtrOffset - Virtual function table offset. Only for MS layout.
+ CharUnits VFPtrOffset;
+
/// VBPtrOffset - Virtual base table offset. Only for MS layout.
CharUnits VBPtrOffset;
@@ -625,7 +628,9 @@
DataSize(0), NonVirtualSize(CharUnits::Zero()),
NonVirtualAlignment(CharUnits::One()),
ZeroLengthBitfield(0), PrimaryBase(0),
- PrimaryBaseIsVirtual(false), VBPtrOffset(CharUnits::fromQuantity(-1)),
+ PrimaryBaseIsVirtual(false),
+ VFPtrOffset(CharUnits::fromQuantity(-1)),
+ VBPtrOffset(CharUnits::fromQuantity(-1)),
FirstNearlyEmptyVBase(0) { }
void Layout(const RecordDecl *D);
@@ -669,7 +674,7 @@
void SelectPrimaryVBase(const CXXRecordDecl *RD);
- void EnsureVTablePointerAlignment();
+ void EnsureVTablePointerAlignment(CharUnits UnpackedBaseAlign);
/// LayoutNonVirtualBases - Determines the primary base class (if any) and
/// lays it out. Will then proceed to lay out all non-virtual base clasess.
@@ -739,8 +744,6 @@
static const CXXMethodDecl *ComputeKeyFunction(const CXXRecordDecl *RD);
virtual ~RecordLayoutBuilder() { }
-
- CharUnits GetVBPtrOffset() const { return VBPtrOffset; }
};
} // end anonymous namespace
@@ -937,9 +940,7 @@
}
void
-RecordLayoutBuilder::EnsureVTablePointerAlignment() {
- CharUnits UnpackedBaseAlign =
- Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(0));
+RecordLayoutBuilder::EnsureVTablePointerAlignment(CharUnits UnpackedBaseAlign) {
CharUnits BaseAlign = (Packed) ? CharUnits::One() : UnpackedBaseAlign;
// The maximum field alignment overrides base align.
@@ -949,7 +950,8 @@
}
// Round up the current record size to pointer alignment.
- setDataSize(getDataSize().RoundUpToAlignment(BaseAlign));
+ setSize(getSize().RoundUpToAlignment(BaseAlign));
+ setDataSize(getSize());
// Update the alignment.
UpdateAlignment(BaseAlign, UnpackedBaseAlign);
@@ -994,9 +996,11 @@
// Under the Itanium ABI, a dynamic class without a primary base has a
// vtable pointer. It is placed at offset 0.
assert(DataSize == 0 && "Vtable pointer must be at offset zero!");
- EnsureVTablePointerAlignment();
CharUnits PtrWidth =
Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
+ CharUnits PtrAlign =
+ Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(0));
+ EnsureVTablePointerAlignment(PtrAlign);
setSize(getSize() + PtrWidth);
setDataSize(getSize());
}
@@ -1032,15 +1036,19 @@
// after any base classes.
CharUnits PtrWidth =
Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
+ CharUnits PtrAlign =
+ Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(0));
+ PtrAlign = std::max(PtrAlign, Alignment);
if (HasNewVirtualFunction(RD) &&
(!PrimaryBase || !BaseHasVFPtr(PrimaryBase))) {
- EnsureVTablePointerAlignment();
+ EnsureVTablePointerAlignment(PtrAlign);
+ VFPtrOffset = getSize();
setSize(getSize() + PtrWidth);
setDataSize(getSize());
}
if (RD->getNumVBases() &&
(!PrimaryBase || !PrimaryBase->getNumVBases())) {
- EnsureVTablePointerAlignment();
+ EnsureVTablePointerAlignment(PtrAlign);
VBPtrOffset = getSize();
setSize(getSize() + PtrWidth);
setDataSize(getSize());
@@ -2030,7 +2038,7 @@
Builder->Layout(RD);
- TargetAlign = Builder->getAligment();
+ TargetAlign = Builder->NonVirtualAlignment;
if (getTargetInfo().getCXXABI() == CXXABI_Microsoft &&
TargetAlign.getQuantity() > 4) {
@@ -2053,7 +2061,7 @@
// FIXME: IsPODForThePurposeOfLayout should be stored in the record layout.
// This does not affect the calculations of MSVC layouts
bool IsPODForThePurposeOfLayout =
- (getTargetInfo().getCXXABI() == CXXABI_Microsoft) ||
+ (getTargetInfo().getCXXABI() != CXXABI_Microsoft) &&
cast<CXXRecordDecl>(D)->isPOD();
// FIXME: This should be done in FinalizeLayout.
@@ -2065,7 +2073,8 @@
NewEntry =
new (*this) ASTRecordLayout(*this, Builder->getSize(),
Builder->Alignment,
- Builder->GetVBPtrOffset(),
+ Builder->VFPtrOffset,
+ Builder->VBPtrOffset,
DataSize,
Builder->FieldOffsets.data(),
Builder->FieldOffsets.size(),
@@ -2175,22 +2184,16 @@
IndentLevel++;
const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+ bool HasVfptr = Layout.getVFPtrOffset() != CharUnits::fromQuantity(-1);
bool HasVbptr = Layout.getVBPtrOffset() != CharUnits::fromQuantity(-1);
// Vtable pointer.
- if (RD->isDynamicClass() && !PrimaryBase) {
+ if (RD->isDynamicClass() && !PrimaryBase &&
+ C.getTargetInfo().getCXXABI() != CXXABI_Microsoft) {
PrintOffset(OS, Offset, IndentLevel);
OS << '(' << *RD << " vtable pointer)\n";
}
- if (HasVbptr && !PrimaryBase) {
- PrintOffset(OS, Offset + Layout.getVBPtrOffset(), IndentLevel);
- OS << '(' << *RD << " vbtable pointer)\n";
-
- // one vbtable per class
- HasVbptr = false;
- }
-
// Dump (non-virtual) bases
for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
E = RD->bases_end(); I != E; ++I) {
@@ -2208,7 +2211,12 @@
Base == PrimaryBase ? "(primary base)" : "(base)",
/*IncludeVirtualBases=*/false);
}
- // vbptr
+
+ // vfptr and vbptr (for Microsoft C++ ABI)
+ if (HasVfptr) {
+ PrintOffset(OS, Offset + Layout.getVFPtrOffset(), IndentLevel);
+ OS << '(' << *RD << " vftable pointer)\n";
+ }
if (HasVbptr) {
PrintOffset(OS, Offset + Layout.getVBPtrOffset(), IndentLevel);
OS << '(' << *RD << " vbtable pointer)\n";
Modified: cfe/trunk/test/Sema/ms_class_layout.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/ms_class_layout.cpp?rev=142694&r1=142693&r2=142694&view=diff
==============================================================================
--- cfe/trunk/test/Sema/ms_class_layout.cpp (original)
+++ cfe/trunk/test/Sema/ms_class_layout.cpp Fri Oct 21 17:49:56 2011
@@ -61,6 +61,12 @@
{
};
+struct I : public virtual D
+{
+ virtual ~I(){}
+ double q;
+};
+
#pragma pack(pop)
// This needs only for building layouts.
@@ -72,18 +78,19 @@
DerivedStruct* v;
H* g;
BaseStruct* u;
+ I* i;
return 0;
}
// CHECK: 0 | class D
-// CHECK-NEXT: 0 | (D vtable pointer)
+// CHECK-NEXT: 0 | (D vftable pointer)
// CHECK-NEXT: 8 | double a
// CHECK-NEXT: sizeof=16, dsize=16, align=8
// CHECK-NEXT: nvsize=16, nvalign=8
// CHECK: 0 | class B
-// CHECK-NEXT: 0 | (B vtable pointer)
+// CHECK-NEXT: 0 | (B vftable pointer)
// CHECK-NEXT: 4 | int b_field
// CHECK-NEXT: sizeof=8, dsize=8, align=4
@@ -91,7 +98,7 @@
// CHECK: 0 | class A
// CHECK-NEXT: 0 | class B (primary base)
-// CHECK-NEXT: 0 | (B vtable pointer)
+// CHECK-NEXT: 0 | (B vftable pointer)
// CHECK-NEXT: 4 | int b_field
// CHECK-NEXT: 8 | int a_field
// CHECK-NEXT: 12 | char one
@@ -101,10 +108,10 @@
// CHECK: 0 | class C
// CHECK-NEXT: 0 | class D (primary base)
-// CHECK-NEXT: 0 | (D vtable pointer)
+// CHECK-NEXT: 0 | (D vftable pointer)
// CHECK-NEXT: 8 | double a
// CHECK-NEXT: 16 | class B (base)
-// CHECK-NEXT: 16 | (B vtable pointer)
+// CHECK-NEXT: 16 | (B vftable pointer)
// CHECK-NEXT: 20 | int b_field
// CHECK-NEXT: 24 | (C vbtable pointer)
// CHECK-NEXT: 32 | double c1_field
@@ -113,23 +120,23 @@
// CHECK-NEXT: 56 | int c4_field
// CHECK-NEXT: 64 | class A (virtual base)
// CHECK-NEXT: 64 | class B (primary base)
-// CHECK-NEXT: 64 | (B vtable pointer)
+// CHECK-NEXT: 64 | (B vftable pointer)
// CHECK-NEXT: 68 | int b_field
// CHECK-NEXT: 72 | int a_field
// CHECK-NEXT: 76 | char one
// CHECK-NEXT: sizeof=80, dsize=80, align=8
-// CHECK-NEXT: nvsize=80, nvalign=8
+// CHECK-NEXT: nvsize=64, nvalign=8
// CHECK: 0 | struct BaseStruct
// CHECK-NEXT: 0 | double v0
// CHECK-NEXT: 8 | float v1
// CHECK-NEXT: 16 | class C fg
// CHECK-NEXT: 16 | class D (primary base)
-// CHECK-NEXT: 16 | (D vtable pointer)
+// CHECK-NEXT: 16 | (D vftable pointer)
// CHECK-NEXT: 24 | double a
// CHECK-NEXT: 32 | class B (base)
-// CHECK-NEXT: 32 | (B vtable pointer)
+// CHECK-NEXT: 32 | (B vftable pointer)
// CHECK-NEXT: 36 | int b_field
// CHECK-NEXT: 40 | (C vbtable pointer)
// CHECK-NEXT: 48 | double c1_field
@@ -138,13 +145,13 @@
// CHECK-NEXT: 72 | int c4_field
// CHECK-NEXT: 80 | class A (virtual base)
// CHECK-NEXT: 80 | class B (primary base)
-// CHECK-NEXT: 80 | (B vtable pointer)
+// CHECK-NEXT: 80 | (B vftable pointer)
// CHECK-NEXT: 84 | int b_field
// CHECK-NEXT: 88 | int a_field
// CHECK-NEXT: 92 | char one
// CHECK-NEXT: sizeof=80, dsize=80, align=8
-// CHECK-NEXT: nvsize=80, nvalign=8
+// CHECK-NEXT: nvsize=64, nvalign=8
// CHECK: sizeof=96, dsize=96, align=8
// CHECK-NEXT: nvsize=96, nvalign=8
@@ -155,10 +162,10 @@
// CHECK-NEXT: 8 | float v1
// CHECK-NEXT: 16 | class C fg
// CHECK-NEXT: 16 | class D (primary base)
-// CHECK-NEXT: 16 | (D vtable pointer)
+// CHECK-NEXT: 16 | (D vftable pointer)
// CHECK-NEXT: 24 | double a
// CHECK-NEXT: 32 | class B (base)
-// CHECK-NEXT: 32 | (B vtable pointer)
+// CHECK-NEXT: 32 | (B vftable pointer)
// CHECK-NEXT: 36 | int b_field
// CHECK-NEXT: 40 | (C vbtable pointer)
// CHECK-NEXT: 48 | double c1_field
@@ -167,12 +174,12 @@
// CHECK-NEXT: 72 | int c4_field
// CHECK-NEXT: 80 | class A (virtual base)
// CHECK-NEXT: 80 | class B (primary base)
-// CHECK-NEXT: 80 | (B vtable pointer)
+// CHECK-NEXT: 80 | (B vftable pointer)
// CHECK-NEXT: 84 | int b_field
// CHECK-NEXT: 88 | int a_field
// CHECK-NEXT: 92 | char one
// CHECK-NEXT: sizeof=80, dsize=80, align=8
-// CHECK-NEXT: nvsize=80, nvalign=8
+// CHECK-NEXT: nvsize=64, nvalign=8
// CHECK: 96 | int x
// CHECK-NEXT: sizeof=104, dsize=104, align=8
@@ -183,14 +190,22 @@
// CHECK-NEXT: sizeof=4, dsize=4, align=4
// CHECK-NEXT: nvsize=4, nvalign=4
-// FIXME: Dump should not be showing vfptr, and vbptr is in the wrong order.
// CHECK: 0 | struct H
-// CHECK-NEXT: 0 | (H vtable pointer)
-// CHECK-NEXT: 4 | (H vbtable pointer)
// CHECK-NEXT: 0 | struct G (base)
// CHECK-NEXT: 0 | int g_field
+// CHECK-NEXT: 4 | (H vbtable pointer)
// CHECK-NEXT: 8 | class D (virtual base)
-// CHECK-NEXT: 8 | (D vtable pointer)
+// CHECK-NEXT: 8 | (D vftable pointer)
// CHECK-NEXT: 16 | double a
// CHECK-NEXT: sizeof=24, dsize=24, align=8
+// CHECK-NEXT: nvsize=8, nvalign=4
+
+// CHECK: 0 | struct I
+// CHECK-NEXT: 0 | (I vftable pointer)
+// CHECK-NEXT: 8 | (I vbtable pointer)
+// CHECK-NEXT: 16 | double q
+// CHECK-NEXT: 24 | class D (virtual base)
+// CHECK-NEXT: 24 | (D vftable pointer)
+// CHECK-NEXT: 32 | double a
+// CHECK-NEXT: sizeof=40, dsize=40, align=8
// CHECK-NEXT: nvsize=24, nvalign=8
More information about the cfe-commits
mailing list