diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2011-10-18 00:55:28 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2011-10-18 00:55:28 +0000 |
commit | 5e9534b0aead93fa921b0feb5beea3f4d7e34c9b (patch) | |
tree | 065f835fda979d9eb5cb7f50064b06def8d0678f /clang/lib/AST | |
parent | 95ff270ee9950a7f8e5b4f07ae9a8838b742df5c (diff) | |
download | bcm5719-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.cpp | 169 |
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); |