void SelectPrimaryVBase(const CXXRecordDecl *RD);
- CharUnits GetVirtualPointersSize(const CXXRecordDecl *RD) const;
+ void EnsureVTablePointerAlignment();
/// LayoutNonVirtualBases - Determines the primary base class (if any) and
/// lays it out. Will then proceed to lay out all non-virtual base clasess.
void AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info,
CharUnits Offset);
+ bool HasNewVirtualFunction(const CXXRecordDecl *RD) const;
+ bool BaseHasVFPtr(const CXXRecordDecl *RD) const;
+
/// LayoutVirtualBases - Lays out all the virtual bases.
void LayoutVirtualBases(const CXXRecordDecl *RD,
const CXXRecordDecl *MostDerivedClass);
void setDataSize(CharUnits NewSize) { DataSize = Context.toBits(NewSize); }
void setDataSize(uint64_t NewSize) { DataSize = NewSize; }
- bool HasVBPtr(const CXXRecordDecl *RD) const;
- bool HasNewVirtualFunction(const CXXRecordDecl *RD) const;
-
- /// Add vbptr or vfptr to layout.
- void AddVPointer();
-
RecordLayoutBuilder(const RecordLayoutBuilder&); // DO NOT IMPLEMENT
void operator=(const RecordLayoutBuilder&); // DO NOT IMPLEMENT
public:
}
}
-CharUnits
-RecordLayoutBuilder::GetVirtualPointersSize(const CXXRecordDecl *RD) const {
- return Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
-}
-
/// DeterminePrimaryBase - Determine the primary base of the given class.
void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) {
// If the class isn't dynamic, it won't have a primary base.
}
}
- // Otherwise, it is the first nearly empty virtual base that is not an
- // indirect primary virtual base class, if one exists.
+ // The Microsoft ABI doesn't have primary virtual bases.
+ if (Context.getTargetInfo().getCXXABI() == CXXABI_Microsoft) {
+ assert(!PrimaryBase && "Should not get here with a primary base!");
+ return;
+ }
+
+ // Under the Itanium ABI, if there is no non-virtual primary base class,
+ // try to compute the primary virtual base. The primary virtual base is
+ // the first nearly empty virtual base that is not an indirect primary
+ // virtual base class, if one exists.
if (RD->getNumVBases() != 0) {
SelectPrimaryVBase(RD);
if (PrimaryBase)
return;
}
- // Otherwise, it is the first nearly empty virtual base that is not an
- // indirect primary virtual base class, if one exists.
+ // Otherwise, it is the first indirect primary base class, if one exists.
if (FirstNearlyEmptyVBase) {
PrimaryBase = FirstNearlyEmptyVBase;
PrimaryBaseIsVirtual = true;
return;
}
- // Otherwise there is no primary base class.
assert(!PrimaryBase && "Should not get here with a primary base!");
-
- // Allocate the virtual table pointer at offset zero.
- assert(DataSize == 0 && "Vtable pointer must be at offset zero!");
-
- // Update the size.
- setSize(getSize() + GetVirtualPointersSize(RD));
- setDataSize(getSize());
-
- CharUnits UnpackedBaseAlign =
- Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(0));
- CharUnits BaseAlign = (Packed) ? CharUnits::One() : UnpackedBaseAlign;
-
- // The maximum field alignment overrides base align.
- if (!MaxFieldAlignment.isZero()) {
- BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
- UnpackedBaseAlign = std::min(UnpackedBaseAlign, MaxFieldAlignment);
- }
-
- // Update the alignment.
- UpdateAlignment(BaseAlign, UnpackedBaseAlign);
}
BaseSubobjectInfo *
}
}
+void
+RecordLayoutBuilder::EnsureVTablePointerAlignment() {
+ CharUnits UnpackedBaseAlign =
+ Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(0));
+ CharUnits BaseAlign = (Packed) ? CharUnits::One() : UnpackedBaseAlign;
+
+ // The maximum field alignment overrides base align.
+ if (!MaxFieldAlignment.isZero()) {
+ BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
+ UnpackedBaseAlign = std::min(UnpackedBaseAlign, MaxFieldAlignment);
+ }
+
+ // Round up the current record size to pointer alignment.
+ setDataSize(getDataSize().RoundUpToAlignment(BaseAlign));
+
+ // Update the alignment.
+ UpdateAlignment(BaseAlign, UnpackedBaseAlign);
+}
+
void
RecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
// Then, determine the primary base class.
}
}
+ if (Context.getTargetInfo().getCXXABI() != CXXABI_Microsoft &&
+ !PrimaryBase && RD->isDynamicClass()) {
+ // 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));
+ setSize(getSize() + PtrWidth);
+ setDataSize(getSize());
+ }
+
// Now lay out the non-virtual bases.
for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
E = RD->bases_end(); I != E; ++I) {
LayoutNonVirtualBase(BaseInfo);
}
+
+ if (Context.getTargetInfo().getCXXABI() == CXXABI_Microsoft) {
+ // Under the MS ABI, there are separate virtual function table and
+ // virtual base table pointers. A vfptr is necessary a if a class defines
+ // a virtual function which is not overriding a function from a base;
+ // a vbptr is necessary if a class has virtual bases. Either can come
+ // from a primary base, if it exists. Otherwise, they are placed
+ // after any base classes.
+ CharUnits PtrWidth =
+ Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
+ if (HasNewVirtualFunction(RD) &&
+ (!PrimaryBase || !BaseHasVFPtr(PrimaryBase))) {
+ EnsureVTablePointerAlignment();
+ setSize(getSize() + PtrWidth);
+ setDataSize(getSize());
+ }
+ if (RD->getNumVBases() &&
+ (!PrimaryBase || !PrimaryBase->getNumVBases())) {
+ EnsureVTablePointerAlignment();
+ VBPtrOffset = getSize();
+ setSize(getSize() + PtrWidth);
+ setDataSize(getSize());
+ }
+ }
}
void RecordLayoutBuilder::LayoutNonVirtualBase(const BaseSubobjectInfo *Base) {
}
}
-void RecordLayoutBuilder::AddVPointer() {
- CharUnits PtrWidth =
- Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
- setSize(getSize() + PtrWidth);
- setDataSize(getSize());
-
- if (Alignment > PtrWidth) {
- setSize(getSize() + (Alignment - PtrWidth));
- setDataSize(getSize());
- }
-}
-
bool
RecordLayoutBuilder::HasNewVirtualFunction(const CXXRecordDecl *RD) const {
for (CXXRecordDecl::method_iterator method = RD->method_begin();
return false;
}
-bool
-RecordLayoutBuilder::HasVBPtr(const CXXRecordDecl *RD) const {
- if (!RD->getNumBases())
- return false;
-
- for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
- E = RD->bases_end(); I != E; ++I) {
- if (!I->isVirtual()) {
- return false;
- }
- }
- return true;
+bool
+RecordLayoutBuilder::BaseHasVFPtr(const CXXRecordDecl *Base) const {
+ // FIXME: This function is inefficient.
+ if (HasNewVirtualFunction(Base))
+ return true;
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base);
+ if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase())
+ return BaseHasVFPtr(PrimaryBase);
+ return false;
}
void
void RecordLayoutBuilder::Layout(const CXXRecordDecl *RD) {
if (Context.getTargetInfo().getCXXABI() == CXXABI_Microsoft) {
- MSLayout(RD);
- return ;
+ //MSLayout(RD);
+ //return ;
}
InitializeLayout(RD);
void RecordLayoutBuilder::MSLayout(const CXXRecordDecl *RD) {
- bool IsVBPtrAddedToLayout = false;
-
InitializeLayout(RD);
- if (HasVBPtr(RD)) {
- // If all bases are virtual and the class declares a new virtual function,
- // MSVC builds a vfptr.
- if (HasNewVirtualFunction(RD)) {
- AddVPointer();
- }
-
- VBPtrOffset = getSize();
- AddVPointer();
- IsVBPtrAddedToLayout = true;
-
- ComputeBaseSubobjectInfo(RD);
- } else {
- LayoutNonVirtualBases(RD);
- }
-
- if (RD->getNumVBases() &&
- !IsVBPtrAddedToLayout) {
- // Add vbptr.
- VBPtrOffset = getSize();
- AddVPointer();
- }
+ LayoutNonVirtualBases(RD);
LayoutFields(RD);