summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2011-10-18 00:55:28 +0000
committerEli Friedman <eli.friedman@gmail.com>2011-10-18 00:55:28 +0000
commit5e9534b0aead93fa921b0feb5beea3f4d7e34c9b (patch)
tree065f835fda979d9eb5cb7f50064b06def8d0678f /clang/lib/AST
parent95ff270ee9950a7f8e5b4f07ae9a8838b742df5c (diff)
downloadbcm5719-llvm-5e9534b0aead93fa921b0feb5beea3f4d7e34c9b.tar.gz
bcm5719-llvm-5e9534b0aead93fa921b0feb5beea3f4d7e34c9b.zip
Rewrite parts of MS ABI C++ layout. Based on work by r4start; I ended up doing this while I was trying to review his patch.
llvm-svn: 142325
Diffstat (limited to 'clang/lib/AST')
-rw-r--r--clang/lib/AST/RecordLayoutBuilder.cpp169
1 files changed, 82 insertions, 87 deletions
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp
index bbd3fc01601..86f4107e688 100644
--- a/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -669,7 +669,7 @@ protected:
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.
@@ -681,6 +681,9 @@ protected:
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);
@@ -730,12 +733,6 @@ protected:
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:
@@ -778,11 +775,6 @@ RecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) {
}
}
-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.
@@ -813,44 +805,30 @@ void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) {
}
}
- // 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 *
@@ -959,6 +937,25 @@ void RecordLayoutBuilder::ComputeBaseSubobjectInfo(const CXXRecordDecl *RD) {
}
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.
DeterminePrimaryBase(RD);
@@ -992,6 +989,18 @@ RecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
}
}
+ 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) {
@@ -1013,6 +1022,30 @@ RecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
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) {
@@ -1061,18 +1094,6 @@ RecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info,
}
}
-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();
@@ -1086,18 +1107,15 @@ RecordLayoutBuilder::HasNewVirtualFunction(const CXXRecordDecl *RD) const {
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
@@ -1244,8 +1262,8 @@ void RecordLayoutBuilder::Layout(const RecordDecl *D) {
void RecordLayoutBuilder::Layout(const CXXRecordDecl *RD) {
if (Context.getTargetInfo().getCXXABI() == CXXABI_Microsoft) {
- MSLayout(RD);
- return ;
+ //MSLayout(RD);
+ //return ;
}
InitializeLayout(RD);
@@ -1753,32 +1771,9 @@ void RecordLayoutBuilder::MSLayoutVirtualBases(const CXXRecordDecl *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);
OpenPOWER on IntegriCloud